[MERGE] merged with latest server

bzr revid: bde@tinyerp.com-20140212100909-rbfkncfa5i9gn7rv
This commit is contained in:
Bharat R. Devnani (OpenERP) 2014-02-12 15:39:09 +05:30
commit 6dca8bf3fb
277 changed files with 23238 additions and 4221 deletions

View File

@ -2,12 +2,11 @@ graft debian
graft doc
graft install
graft openerp
graft tests
graft win32
include README
include LICENSE
include MANIFEST.in
include openerp-wsgi.py
include openerp-server
include openerp-*
include oe*
include setup*
global-exclude *pyc *~ # Exclude possible garbage from previous graft.

View File

@ -172,40 +172,80 @@ is as follows:
</data>
</openerp>
Record Tag
//////////
``<record>``
////////////
**Description**
Defines a new record in a specified OpenERP model.
The addition of new data is made with the record tag. This one takes a
mandatory attribute : model. Model is the object name where the insertion has
to be done. The tag record can also take an optional attribute: id. If this
attribute is given, a variable of this name can be used later on, in the same
file, to make reference to the newly created resource ID.
``@model`` (required)
A record tag may contain field tags. They indicate the record's fields value.
If a field is not specified the default value will be used.
Name of the model in which this record will be created/inserted.
The Record Field tag
////////////////////
``@id`` (optional)
The attributes for the field tag are the following:
:term:`external ID` for the record, also allows referring to this record in
the rest of this file or in other files (through ``field/@ref`` or the
:py:func:`ref() <openerp.tools.convert._ref>` function)
name : mandatory
the field name
A record tag generally contains multiple ``field`` tags specifying the values
set on the record's fields when creating it. Fields left out will be set to
their default value unless required.
eval : optional
python expression that indicating the value to add
ref
reference to an id defined in this file
``<field>``
///////////
model
model to be looked up in the search
In its most basic use, the ``field`` tag will set its body (as a string) as
the value of the corresponding ``record``'s ``@name`` field.
search
a query
Extra attributes can either preprocess the body or replace its use entirely:
``@name`` (mandatory)
Name of the field in the containing ``record``'s model
``@type`` (optional)
One of ``char``, ``int``, ``float``, ``list``, ``tuple``, ``xml`` or
``html``, ``file`` or ``base64``. Converts the ``field``'s body to the
specified type (or validates the body's content)
* ``xml`` will join multiple XML nodes under a single ``<data>`` root
* in ``xml`` and ``html``, external ids can be referenced using
``%(id_name)s``
* ``list`` and ``tuple``'s element are specified using ``<value>``
sub-nodes with the same attributes as ``field``.
* ``file`` expects a module-local path and will save the path prefixed with
the current module's name, separated by a ``,`` (comma). For use with
:py:func:`~openerp.modules.module.get_module_resource`.
* ``base64`` expects binary data, encodes it to base64 and sets it. Mostly
useful with ``@file``
``@file``
Can be used with types ``char`` and ``base64``, sources the field's content
from the specified file instead of the field's text body.
``@model``
Model used for ``@search``'s search, or registry object put in context for
``@eval``. Required if ``@search`` but optional if ``@eval``.
``@eval`` (optional)
A Python expression evaluated to obtain the value to set on the record
``@ref`` (optional)
Links to an other record through its :term:`external id`. The module prefix
may be ommitted to link to a record defined in the same module.
``@search`` (optional)
Search domain (evaluated Python expression) into ``@model`` to get the
records to set on the field.
Sets all the matches found for m2m fields, the first id for other field
types.
**Example**

98
doc/06_ir_qweb.rst Normal file
View File

@ -0,0 +1,98 @@
.. _qweb:
====
QWeb
====
``t-field``
===========
The server version of qweb includes a directive dedicated specifically to
formatting and rendering field values from
:class:`~openerp.osv.orm.browse_record` objects.
The directive is implemented through
:meth:`~base.ir.ir_qweb.QWeb.render_tag_field` on the ``ir.qweb`` openerp
object, and generally delegates to converters for rendering. These converters
are obtained through :meth:`~base.ir.ir_qweb.QWeb.get_converter_for`.
By default, the key for obtaining a converter is the type of the field's
column, but this can be overridden by providing a ``widget`` as field option.
Field options are specified through ``t-field-options``, which must be a JSON
object (map). Custom widgets may define their own (possibly mandatory) options.
Global options
--------------
A global option ``html-escape`` is provided. It defaults to ``True``, and for
many (not all) fields it determines whether the field's output will be
html-escaped before being output.
Date and datetime converters
----------------------------
The default rendering for ``date`` and ``datetime`` fields. They render the
field's value according to the current user's ``lang.date_format`` and
``lang.time_format``. The ``datetime`` converter will also localize the value
to the user's timezone (as defined by the ``tz`` context key, or the timezone
in the user's profile if there is no ``tz`` key in the context).
A custom format can be provided to use a non-default rendering. The custom
format uses the ``format`` options key, and uses the
`ldml date format patterns`_ [#ldml]_.
For instance if one wanted a date field to be rendered as
"(month) (day of month)" rather than whatever the default is, one could use:
.. code-block:: xml
<span t-field="object.datefield" t-field-options='{"format": "MMMM d"}'/>
Monetary converter (widget: ``monetary``)
-----------------------------------------
Used to format and render monetary value, requires a ``display_currency``
options value which is a path from the rendering context to a ``res.currency``
object. This object is used to set the right currency symbol, and set it at the
right position relative to the formatted value.
The field itself should be a float field.
Relative Datetime (widget: ``relative``)
----------------------------------------
Used on a ``datetime`` field, formats it relatively to the current time
(``datetime.now()``), e.g. if the field's value is 3 hours before now and the
user's lang is english, it will render to *3 hours ago*.
.. note:: this field uses babel's ``format_timedelta`` more or less directly
and will only display the biggest unit and round up at 85% e.g.
1 hour 15 minutes will be rendered as *1 hour*, and 55 minutes will
also be rendered as *1 hour*.
.. warning:: this converter *requires* babel 1.0 or more recent.
Duration (widget: ``duration``)
-------------------------------
Renders a duration defined as a ``float`` to a human-readable localized string,
e.g. ``1.5`` as hours in an english locale will be rendered to
*1 hour 30 minutes*.
Requires a ``unit`` option which may be one of ``second``, ``minute``,
``hour``, ``day``, ``week``, ``month`` or ``year``. This specifies the unit in
which the value should be interpreted before formatting.
The duration must be a positive number, and no rounding is applied.
.. [#ldml] in part because `babel`_ is used for rendering, as ``strftime``
would require altering the process's locale on the fly in order to
get correctly localized date and time output. Babel uses the CLDR
as its core and thus uses LDML date format patterns.
.. _babel: http://babel.pocoo.org
.. _ldml date format patterns:
http://www.unicode.org/reports/tr35/tr35-dates.html#Date_Format_Patterns

View File

@ -11,3 +11,4 @@ Miscellanous
06_misc_user_img_specs.rst
06_misc_import.rst
06_misc_auto_join.rst
06_ir_qweb.rst

View File

@ -252,5 +252,4 @@ texinfo_documents = [
# Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {
'python': ('http://docs.python.org/', None),
'openerpweb': ('http://doc.openerp.com/trunk/developers/web', None),
}

View File

@ -12,26 +12,20 @@ Server actions
.. currentmodule:: openerp.addons.base.ir.ir_actions
.. autoclass:: actions_server
:noindex:
.. autoclass:: ir_actions_server
:members: run, _get_states
Adding a new sever action
-------------------------
The ``state`` field holds the various available types of server action. In order
to add a new server action, the first thing to do is to override the ``_get_states``
to add a new server action, the first thing to do is to override the :meth:`~.ir_actions_server._get_states`
method that returns the list of values available for the selection field.
.. automethod:: actions_server._get_states
:noindex:
The method called when executing the server action is the ``run`` method. This
The method called when executing the server action is the :meth:`~.ir_actions_server.run` method. This
method calls ``run_action_<STATE>``. When adding a new server action type, you
have to define the related method that will be called upon execution.
.. automethod:: actions_server.run
:noindex:
Changelog
---------

View File

@ -19,17 +19,27 @@
#
##############################################################################
""" OpenERP core library..
"""
import sys
""" OpenERP core library."""
#----------------------------------------------------------
# Running mode flags (gevent, prefork)
#----------------------------------------------------------
# Is the server running with gevent.
import sys
evented = False
if sys.modules.get("gevent") is not None:
evented = True
# Is the server running in pefork mode (e.g. behind Gunicorn).
# If this is True, the processes have to communicate some events,
# e.g. database update or cache invalidation. Each process has also
# its own copy of the data structure and we don't need to care about
# locks between threads.
multi_process = False
#----------------------------------------------------------
# libc UTC hack
#----------------------------------------------------------
# Make sure the OpenERP server runs in UTC. This is especially necessary
# under Windows as under Linux it seems the real import of time is
# sufficiently deferred so that setting the TZ environment variable
@ -40,9 +50,22 @@ import time # ... *then* import time.
del os
del time
#----------------------------------------------------------
# Shortcuts
#----------------------------------------------------------
# The hard-coded super-user id (a.k.a. administrator, or root user).
SUPERUSER_ID = 1
def registry(database_name):
"""
Return the model registry for the given database. If the registry does not
exist yet, it is created on the fly.
"""
return modules.registry.RegistryManager.get(database_name)
#----------------------------------------------------------
# Imports
#----------------------------------------------------------
import addons
import cli
import conf
@ -58,23 +81,6 @@ import service
import sql_db
import tools
import workflow
# backward compatilbility
# TODO: This is for the web addons, can be removed later.
wsgi = service
wsgi.register_wsgi_handler = wsgi.wsgi_server.register_wsgi_handler
# Is the server running in multi-process mode (e.g. behind Gunicorn).
# If this is True, the processes have to communicate some events,
# e.g. database update or cache invalidation. Each process has also
# its own copy of the data structure and we don't need to care about
# locks between threads.
multi_process = False
def registry(database_name):
"""
Return the model registry for the given database. If the registry does not
exist yet, it is created on the fly.
"""
return modules.registry.RegistryManager.get(database_name)
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -34,7 +34,4 @@ Importing them from here is deprecated.
"""
# get_module_path is used only by base_module_quality
from openerp.modules import get_module_resource, get_module_path
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -25,6 +25,7 @@ import module
import res
import report
import test
import tests
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -92,8 +92,6 @@ The kernel of OpenERP, needed for all installation.
],
'test': [
'test/base_test.yml',
'test/test_context.xml',
'test/bug_lp541545.xml',
'test/test_osv_expression.yml',
'test/test_ir_rule.yml', # <-- These tests modify/add/delete ir_rules.
],

View File

@ -112,18 +112,6 @@ CREATE TABLE ir_act_client (
)
INHERITS (ir_actions);
CREATE TABLE ir_ui_view (
id serial NOT NULL,
name varchar(64) DEFAULT ''::varchar NOT NULL,
model varchar(64) DEFAULT ''::varchar NOT NULL,
"type" varchar(64) DEFAULT 'form'::varchar NOT NULL,
arch text NOT NULL,
field_parent varchar(64),
priority integer DEFAULT 5 NOT NULL,
primary key(id)
);
CREATE TABLE ir_ui_menu (
id serial NOT NULL,
parent_id int references ir_ui_menu on delete set null,
@ -409,4 +397,4 @@ insert into ir_model_data (name,module,model,noupdate,res_id) VALUES ('main_comp
select setval('res_company_id_seq', 2);
select setval('res_users_id_seq', 2);
select setval('res_partner_id_seq', 2);
select setval('res_currency_id_seq', 2);
select setval('res_currency_id_seq', 2);

View File

@ -91,6 +91,25 @@ Administrator</field>
<field eval="10" name="sequence"/>
</record>
<!--
A group dedicated to the portal users, making groups
restrictions more convenient.
-->
<record id="group_portal" model="res.groups">
<field name="name">Portal</field>
<field name="comment">Portal members have specific access rights (such as record rules and restricted menus).
They usually do not belong to the usual OpenERP groups.</field>
</record>
<!--
A group dedicated to the public user only, making groups
restrictions more convenient.
-->
<record id="group_public" model="res.groups">
<field name="name">Public</field>
<field name="comment">Public users have specific access rights (such as record rules and restricted menus).
They usually do not belong to the usual OpenERP groups.</field>
</record>
<!-- Basic fonts family included in PDF standart, will always be in the font list -->
<record model="res.font" id="base.font_helvetica">
<field name="name">Helvetica</field>
@ -111,5 +130,21 @@ Administrator</field>
<field name="mode">all</field>
</record>
<record id="public_partner" model="res.partner">
<field name="name">Public user</field>
<field name="active" eval="False"/>
</record>
<record id="public_user" model="res.users">
<field name="name">Public user</field>
<field name="login">public</field>
<field name="password"></field>
<!-- Avoid auto-including this demo user in any default group -->
<field name="groups_id" eval="[(6,0,[ref('base.group_public')])]"/>
<field name="image" type="base64" file="base/static/img/public_user-image.png"/>
<field name="partner_id" ref="public_partner"/>
<field name="active" eval="False"/>
</record>
</data>
</openerp>

View File

@ -1,80 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="1">
<record id="partner_demo" model="res.partner">
<field name="name">Demo User</field>
<field name="company_id" ref="main_company"/>
<field name="customer" eval="False"/>
<field name="email">demo@example.com</field>
<field name="email">demo@yourcompany.example.com</field>
<field name="street">Avenue des Dessus-de-Lives, 2</field>
<field name="city">Namur (Loyers)</field>
<field name="zip">5101</field>
<field name="country_id" ref="be"/>
</record>
<record id="main_partner" model="res.partner">
<field name="image">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
BZrmED0AAAAASUVORK5CYII=
</field>
<field name="name">YourCompany</field>
<field name="street">1725 Slough Ave.</field>
<field name="city">Scranton</field>
<field name="zip">18540</field>
<field name="phone">+1 555 123 8069</field>
<field name="email">info@yourcompany.example.com</field>
<field name="website">www.example.com</field>
<field name="image" type="base64" file="base/static/img/main_partner-image.png"/>
</record>
<record id="main_company" model="res.company">
<field name="name">YourCompany</field>
</record>
<record id="user_demo" model="res.users">
<field name="partner_id" ref="base.partner_demo"/>
<field name="login">demo</field>
@ -83,160 +37,13 @@ BZrmED0AAAAASUVORK5CYII=
Mr Demo</field>
<field name="company_id" ref="main_company"/>
<field name="groups_id" eval="[(6,0,[ref('base.group_user'), ref('base.group_partner_manager')])]"/>
<field name="image">/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAUDBAQEAwUEBAQFBQUGBwwIBwcHBw8LCwkMEQ8SEhEP
ERETFhwXExQaFRERGCEYGh0dHx8fExciJCIeJBweHx7/2wBDAQUFBQcGBw4ICA4eFBEUHh4eHh4e
Hh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh7/wAARCACEAIQDASIA
AhEBAxEB/8QAHQABAAICAwEBAAAAAAAAAAAAAAYIBQcBAgQDCf/EADcQAAEDAwIEBAMHBAIDAAAA
AAECAwQABREGEgchMUETIlFhMnGBCBQVI0KRoTNSYsFD0bHw8f/EABoBAAIDAQEAAAAAAAAAAAAA
AAAFAQMEBgL/xAAoEQACAgEDAwQBBQAAAAAAAAAAAQIDEQQSIQUxQRMiMlGBM2FxkbH/2gAMAwEA
AhEDEQA/ALl0pSgBSlcKoAHr1rBuar0+3eHLO9dY7M9A3FhxW1ZHtnr9KjnEHidYtITFQp7gD20H
ry5jp8/n1qnHEPXNw1frFUpc3x0bvyvERtDYPRGOqT9eveqbLdvbuaKqN/y7F7rZqC2Ti+hEttLj
LhQpClYPqCB1wR/uu7l+s7aQtVxj7Scbg4MA+h9PrVF42pdTLaVERcXXmQhKPDcwpbRR0KV/EMZP
fvXsm6kv/gJedf3SUc3SlQ/MSO59/nVMtVjsi+Ojz3Ze5lxDjYWhYUlQyCD1r6Cq18BeKw/FWLNc
5YTBebUn81XNl0cxg+ihkexA9asihaVICgchQyCKvqsU45Ml1Trlg7ilBSrSsUpSgBSlKAFKUoAU
pSgDhRqIcStbQtIWnxlbH5jh2ssBYCs46kHtUskLQ00t1xQShCSpSj0AHWqbcYNcQtZ6nkz2oq2r
fHSpmMVfE7g48QgdAew9Kqts2LJfp6vUljwQjiPeL7rHUbtyuW0LOUjYrHlzyBx6dBUQRbpCHVJZ
baKeXiBQyTz657GstbkPSpqlDdHWPhPYj3FSOFAUtK1OZz0K0JyKWyt55HEaOODCRorzriJTMxtu
QjoR0Xj9Kx/uvRcELU63JaWqK5gFThG7w/UKH6k/6rPQbYJTgKPDCweRGMH51l29IzrgnwIrRKjy
OByx6VmlcsmmOneDU97XOgXJLyEpYWFBeGj5DzyMe1bD4Ycc9Z6XuCROlv3e3PyPFfZeWCoDoUoJ
+AdDj2rLz+FEpUFSZStqgnyAHOPatbX7SsqzKdQs7klIUnd3PPIqynVrsVX6J4yy/HDrWdq1xp9u
82nxUNqJStpwYW2odQe1ScVR3gHxL1Bpq5N2O373YhdBVD8ML8bJ54OQUq64xV3IT6JMVqQgKCXU
BYCk4UAR3HY03qs3oRXVOuR9qUFKtKRSlKAFKUoAUNKUAa94432TadFT2IicLkRXQtzaVbEYwenT
OcZPIVS8MP3OwMxWwd4UduOWU56mrj/aOZdkcNZcZokFxadxGcbRzIOO2BVadB2hCr5b2F5WiRH8
bB7Jzn+c0t1s2mOOnVpomHD/AIZLlaa8aW9tkq2lhahk7cd6zMfhdc3JJQ5IR4f95/6qfW55DDKG
m8BpICRz7dqzTDpLfTpS1S3PkcSzH4kHtXDO3wcKdfU6rOfQVJodtiwGw1HQlPvisi6sq5ivg4o4
5kVVL9iIOT7njnRW3mSCkE461q/Xmn25drmIQ0lTpQS3kd//AJW0nlr2nBxWBuDYVkGss5YkmjVF
ZjgqyY70KaFtb2JaSNricghQ5jpV5+D2oDqfh1Z7s48XZC44RIJxnxU8lA49xVZOIemkMTlyIzZL
b4Khj9JHYHt6/Ktg/ZUvT0O43HTspeGpCRJjg8sODksD6YOPY060GoTeG+4i6lp/bleCxIpXCOlc
05EYpSlAClKUAKHpSlAEJ41x3ZHDy5IaSVYR5wOuzvVW9Mzhb9XPFxeAy2hpHoAAOQ/erk6lhidY
LhDx/WjrQPmUnH81RbXDzkK7x7g2NoeUA4PRaeSh/GaXa2OXkbdOswsFgrVN3tJUTkHmKlFre8RA
51rW2XNiJZUTJStjYaSr55HSuydV6hdjlVlsLgbI8rz52px64pPGLzkfNprBtNzuArka64TjzVp9
HEV23ub7rNZ3A4WGzuGfpU307fhfLeqTGewg8gSOZqJTx4CNWVwerUGpYVsBbaiuTJBHJCKwcZvV
N+P3lTMazxxzSlSty1/SopqpGobjdDFgvGCzglUhCRu5dOZ9/SuNDaO1GiCr8f1NOXJU4pSXUSSo
7dxKQE4wPLgfSphFSg5NhKMoSUUvySC/W+S/bn4zq2lObSWlt5wFdjg9OdRzhJIWnVcGY6tTJU+2
lYCefiBWFD2/3k1sFq1hhnap9b6sfEvqfesXpiBFs+pX0yWkmNJWmSyf7Hd2DVNVm2fB7upUo88l
g0fDXNdGFbmkqHcZrvXXLlHEtYYpSlSQKUpQApSlAHVfvVNvtC6c/D9aToUZhQhufnN4HwqUCT/5
xVylda11xX06h4KvrMZL7gYLD6FDIKf0n5jmM+9ZtVFuGfo3dPcfV2yeM/6aM0881M0XbJbyA4pD
YG08xuAxzrzTrbf9Ub2X7j9wtwRhplLhSVH+5XqPas5aLY7BskrCAGUO+IgDmAFdvbBrI23Y/wAi
Ej0z3pNzGSwdPCG6LizXMHQrVpgxba46J3gOlxTxGMnJ6nv1/gVsTS7yY7qEJ2jxDjCeQPblXS/q
ZjtJDmVqVySkdKwku4IiFl5T6EcwQcgYNeLZucss1UUxhHaifFlkzMpQjPMK39BXraj4dAbUkewr
FQVtToiXlyAtO0FzZz/mvs7KiBkgrUkIPlOfMD7VgllMuccEhcRtaBJ51i1QjLuMdTjoS1G3OFOM
7lYwn9s16mHFOQ0nxN4xkK9ayej0Ic1JGS4gKSoK5H1AyKipb7VFeTLdP0qpT+jZNsChb2AoEKDa
c569K9FcI6VzXaRWEkcLJ5bYpSlSQKUpQApSlAHBrz3CM3LhuxXk5bdQUq+Rr0d64IqGsgm08o0P
e4CrTLnWyQT4hSpGSMeKnqFAd6glsmuMy0NE4AVirT3W2xLjHUxLZC0K+hH1qsPEWyyNNaofjrQo
ICtzSz0Wk9D/AKpRrNO4RzE6XQa5XSxLhmQvkuO1EU8sEkJ9M9airkG23J9qRPaipCDyLmDjPpWa
C7ZfdPORFuEKxhac4I9PfFRF3TcOJMQFsvOIz+t5Sh/JpdWs5UmO4yz37EwjXKxWxpTUeelLOPM2
yrJUflWYjzzcmFRrVZHG9w/rSxhITjrjqflyrEWiNaoiAtuHFY6DagblGp9BkNOQkhISgKGAAK82
enFPyXSdSXtWT4aUbmMWRDNxUlchAO5SU4B5+lSjRLZd1O1tHJptS1Y7dhUcnPCMyFBYyP0jvUr4
TKS45NcUPO4lJBPXbzGK8aCvfqIirqVm3TzaNgp6VzXArmuuOOFKUoAUpSgBSlKAFKUoA6q61rzj
zbLdK0Y5MlMbn2XEJacHxDccEe/yrYautVs4wcYrbetbzeG9tYC2oBBkTCr45CCCW0D0TnmT35dj
XquEbJKMuzJU5Q90e5qS5SJlmn7sqCc+VzsoVmrJqZh4JS9hXPmK90thMhOxxCVpVywoZBrHSuHb
0kfeLXIEdzGQlXwn/qqdX0FrMqnka6TrmMKxE1sUmPOc3AJ24OPSsxFmx0Jx4uFA4AzWvrNYNRW1
wJlnwAeQXzKT+1TCDpxSm0OvSluFRzhPJIrl9RROqWJrB0dWrhbHMOT0PS37hIDMcOFGcK/xA96z
k/VUzQ9pYvjDQeZbeabltf3NKVgkehGQa9FrhsR4u1ASMDBI71G+K62lcPLjGUQFvBDLYPdalpCQ
PfNGkcoWxx9lGqirKpJ/RYy2S2J9vYmxlBTL7aXEH2IzXpqGcJZviaWZtzh/NhpCMeqe1TJJ5da6
6UdrwcbnJzSlK8gKUpQApSlAClMio5r/AFrpnQ1k/F9TXRuDGKvDbGCpx5eCdqEDmo4BOAKAMdxq
1vG4fcOrpqV7CnmWvDhtE/1ZC/K2n9yPpX5yaXushvXEK5Sny68/LJkuq6rU6SVK+qjmtifaY4uv
cT9RsM25EqJYLeD91jPgBTjpyFPKAJ545JHYE+tafWjKcYHyqFLbJNeD0o8FuY0cPhG3BwnJPtUt
060H4iFbTtTyPtVZuFPFJyyuos+qXFPWxXkRMOVORx/l3UntnqPftaTSK47traeivtvMPJDja0K3
BST0OR1p5XfG2OV3MM63BmR2o2bdoKRywa6JisDKmB4RPUJ6ftX0UQFkAg+9EkNrznkexqLaYXLb
NZJrunW8xeDyyj92aU466httIJUvGBgevpWqL3rHTt81fDQ/fYLFltjhcbU45gSH8YCz22pycZ78
+wrL/aF1s1p3R33OK7i4XjdGjYIy23j8x36DkPciq120sLaKEbSrGACMgDtypHHpNFWo3Rf4HEuq
3W07Gi7+k9RxLYE3xl377AXHUpZikOeIkDPkwcKPKpJpDjRwz1R4aLbquE0+58MeYTHcPyC8Z+ma
pZwQ1fJ0rrIWt95Rs1wc2PNKVlLKzna6kdBz5K9QQe1YrjPp5WmdfzYraR9xnkzIh6jCz50/IK5/
JQ9K16j3Lf8A2LocPB+k7TqHUBxpaVoPRSSCD9RXfIxnNfmXoziBq/SjyVaf1HcbcE4/KQ9vZx6e
GrKf4rfvDz7Vlzafai64sjMtg8lTbcNjifdTROFe5SR7JrIpFziW4pWtLXx14VzoaZI1bFjbv+OU
hbSx80kUqcojDNl0pSoIOqzjH/vavzX426zv+s+Id0nXyX4n3OZIhRGW8pajstulAShOTjO3Kj1J
9gAFKlnpEBkHl4o5KGPrXZY5A0pXhns6KSDnPYZrbX2XtVXqHq9OkkSt9olNLe8FzzeCtJHNB/SD
nmOY9hSlXadtTRVb2LQSiUqKQT5TgV5HnFrbbSTgKODj50pT5i8rF9qIrXxGUtTiyGWUMNIz5W0A
ZwB7k5Prgela0t77jb6ClXUUpSm79U2Q+Jn2gHLJc7tgJlQHmlsqHQnOfMO45Vsnjc/+LcNLfdZL
TaZMG6NMslsYAbdjhSkn2ycj5ClK9v4S/gjyjTYAU2CeoruwtQO3qPelKWmk96HnEpAStQHso0pS
gk//2Q==</field>
<field name="image" type="base64" file="base/static/img/user_demo-image.jpg"/>
</record>
<record model="res.partner" id="base.partner_root">
<field name="email">admin@example.com</field>
<field name="email">admin@yourcompany.example.com</field>
<field name="tz">Europe/Brussels</field>
<field name="image">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
kALR5oiAU7jnCuj0RFIHQbIiKAf/2Q==</field>
<field name="image" type="base64" file="base/static/img/partner_root-image.jpg"/>
</record>
<!-- new rate for demo transactions in multi currency -->

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:27+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:36+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:28+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:36+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
@ -60,12 +60,12 @@ msgstr "Kyk na argitektuur"
#. module: base
#: model:ir.module.module,summary:base.module_sale_stock
msgid "Quotation, Sale Orders, Delivery & Invoicing Control"
msgstr ""
msgstr "Kwotasie, Bestellins, Aflewerings en Faktuur beheer."
#. module: base
#: selection:ir.sequence,implementation:0
msgid "No gap"
msgstr ""
msgstr "Geep Spasie"
#. module: base
#: selection:base.language.install,lang:0
@ -89,23 +89,24 @@ msgstr ""
#. module: base
#: model:ir.module.module,summary:base.module_point_of_sale
msgid "Touchscreen Interface for Shops"
msgstr ""
msgstr "Tasskerm koppelvlak vir Winkels"
#. module: base
#: model:ir.module.module,shortdesc:base.module_l10n_in_hr_payroll
msgid "Indian Payroll"
msgstr ""
msgstr "Indiese Betaalstaat"
#. module: base
#: help:ir.cron,model:0
msgid ""
"Model name on which the method to be called is located, e.g. 'res.partner'."
msgstr ""
"Model naam waarin die metode wat geroep word verskyn, bv. \"res.partner\"."
#. module: base
#: view:ir.module.module:0
msgid "Created Views"
msgstr ""
msgstr "Geskepte Afbeelding"
#. module: base
#: model:ir.module.module,description:base.module_product_manufacturer
@ -122,11 +123,24 @@ msgid ""
" * Product Attributes\n"
" "
msgstr ""
"\n"
"'n Module wat die vervaardegiers en eienskappe van die produk op die vorm "
"byvoeg.\n"
"===================================================================\n"
"\n"
"Jy behoort nu die volgende vir produkte te kan definieer:\n"
"-----------------------------------------------------------------------------"
"--\n"
" * Vervaardiger\n"
" * Vervaardiger Produk Naame\n"
" * Vervaardiger Produk Kode\n"
" * Produk Eienskappe\n"
" "
#. module: base
#: field:ir.actions.client,params:0
msgid "Supplementary arguments"
msgstr ""
msgstr "Aanvullende argumente"
#. module: base
#: model:ir.module.module,description:base.module_google_base_account
@ -135,11 +149,14 @@ msgid ""
"The module adds google user in res user.\n"
"========================================\n"
msgstr ""
"\n"
"Hierdie module voeg google user bu res.user.\n"
"=====================================\n"
#. module: base
#: help:res.partner,employee:0
msgid "Check this box if this contact is an Employee."
msgstr ""
msgstr "Selekteer hierdie block as die kontak 'n Verknemer is."
#. module: base
#: help:ir.model.fields,domain:0

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:28+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:37+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
@ -366,7 +366,7 @@ msgstr "አክቲቭ"
#. module: base
#: field:ir.actions.wizard,wiz_name:0
msgid "Wizard Name"
msgstr "የዊዘርዱ ስም"
msgstr ""
#. module: base
#: model:ir.module.module,description:base.module_knowledge
@ -481,7 +481,7 @@ msgstr ""
msgid ""
"One of the records you are trying to modify has already been deleted "
"(Document type: %s)."
msgstr "ለማሻሻል የሞከሩት ሰነድ ከዚህ በፊት የተሰረዘ ሆኖ ተገኝትዋል (የሰነዱ አይነት፡ %s)።"
msgstr ""
#. module: base
#: help:ir.actions.act_window,views:0

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:28+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:37+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:29+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:38+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

15317
openerp/addons/base/i18n/bn.po Normal file

File diff suppressed because it is too large Load Diff

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:28+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:38+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:29+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:38+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -7,14 +7,14 @@ msgstr ""
"Project-Id-Version: openobject-server\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2012-12-21 17:04+0000\n"
"PO-Revision-Date: 2012-08-20 15:44+0000\n"
"Last-Translator: Jiří Hajda <robie@centrum.cz>\n"
"PO-Revision-Date: 2014-01-05 20:16+0000\n"
"Last-Translator: Maros Tarbajovsky <openerp.cz@gmail.com>\n"
"Language-Team: openerp-i18n-czech <openerp-i18n-czech@lists.launchpad.net>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:29+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:38+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Poedit-Language: Czech\n"
#. module: base
@ -38,7 +38,7 @@ msgstr "Svatá Helena"
#. module: base
#: view:ir.actions.report.xml:0
msgid "Other Configuration"
msgstr "Další nastavení"
msgstr "Ostatní nastavení"
#. module: base
#: selection:ir.property,type:0
@ -59,7 +59,7 @@ msgstr ""
#: field:ir.ui.view,arch:0
#: field:ir.ui.view.custom,arch:0
msgid "View Architecture"
msgstr "Architektura zobrazení"
msgstr "Zobrazení architektury"
#. module: base
#: model:ir.module.module,summary:base.module_sale_stock
@ -69,7 +69,7 @@ msgstr "Nabídky, zakázky, řízení dopravy a fakturace"
#. module: base
#: selection:ir.sequence,implementation:0
msgid "No gap"
msgstr "Bez mezer"
msgstr "Bez mezery"
#. module: base
#: selection:base.language.install,lang:0
@ -769,8 +769,7 @@ msgstr "Server odchozí pošty"
msgid ""
"Context dictionary as Python expression, empty by default (Default: {})"
msgstr ""
"Kontextový slovník jako výraz Pythonu, výchozí hodnota je prázdný slovník "
"(výchozí: {})"
"Kontextový slovník jako výraz Pythonu, jako výchozí je prázdné (Výchozí: {})"
#. module: base
#: field:res.company,logo_web:0
@ -7554,7 +7553,7 @@ msgstr "Spojené království"
#. module: base
#: model:ir.module.module,shortdesc:base.module_l10n_pa
msgid "Panama Localization Chart Account"
msgstr ""
msgstr "Panamská účtová osnova"
#. module: base
#: help:res.partner.category,active:0
@ -8390,7 +8389,7 @@ msgstr "Portál reklamací"
#. module: base
#: model:ir.module.module,shortdesc:base.module_l10n_pe
msgid "Peru Localization Chart Account"
msgstr ""
msgstr "Peruánská účtová osnova"
#. module: base
#: model:ir.module.module,description:base.module_auth_oauth
@ -8399,6 +8398,9 @@ msgid ""
"Allow users to login through OAuth2 Provider.\n"
"=============================================\n"
msgstr ""
"\n"
"Povolit uživatelům přihlášení přes OAuth2 Provider.\n"
"=============================================\n"
#. module: base
#: model:ir.actions.act_window,name:base.action_model_fields
@ -9333,7 +9335,7 @@ msgstr "Stránka dokumentu"
#. module: base
#: model:ir.module.module,shortdesc:base.module_l10n_ar
msgid "Argentina Localization Chart Account"
msgstr ""
msgstr "Argentinská účtová osnova"
#. module: base
#: field:ir.module.module,description_html:0
@ -9941,6 +9943,10 @@ msgid ""
"=============================\n"
"\n"
msgstr ""
"\n"
"OpenERP webové zobrazení Ganttova diagramu.\n"
"===========================================\n"
"\n"
#. module: base
#: model:ir.module.module,shortdesc:base.module_base_status
@ -10216,6 +10222,15 @@ msgid ""
"If set to true it allows user to cancel entries & invoices.\n"
" "
msgstr ""
"\n"
"Umožňuje zrušení účetních zápisů.\n"
"====================================\n"
"\n"
"Tento modul přidává pole \"Povolit zrušení položek\" na formuláři deník "
"účtů.\n"
"Pokud je nastaven na hodnotu true, umožňuje uživateli zrušit záznamy & "
"faktury.\n"
" "
#. module: base
#: model:ir.module.module,shortdesc:base.module_plugin
@ -10378,6 +10393,10 @@ msgid ""
"=========================\n"
"\n"
msgstr ""
"\n"
"Zobrazení Openerp Web Diagramu.\n"
"=========================\n"
"\n"
#. module: base
#: model:ir.module.module,description:base.module_l10n_ch
@ -10776,6 +10795,11 @@ msgid ""
"=======================\n"
"\n"
msgstr ""
"\n"
"OpenERP Webová testovací sestava.\n"
"\n"
"==================================\n"
"\n"
#. module: base
#: view:ir.model:0
@ -10978,6 +11002,12 @@ msgid ""
"This module gives the details of the goods traded between the countries of\n"
"European Union."
msgstr ""
"\n"
"Modul, který přidává výkazy pro Intrastat.\n"
"=====================================\n"
"\n"
"Tento modul poskytuje údaje o zboží obchodovaného mezi zeměmi\n"
"Evropské unie."
#. module: base
#: help:ir.actions.server,loop_action:0
@ -11162,7 +11192,7 @@ msgstr "%A - Plný název dne v týdnu."
#. module: base
#: help:ir.values,user_id:0
msgid "If set, action binding only applies for this user."
msgstr ""
msgstr "Je-li nastavena, závaznost akce platí pouze pro tohoto uživatele."
#. module: base
#: model:res.country,name:base.gw
@ -11389,6 +11419,15 @@ msgid ""
"associated to every resource. It also manages the leaves of every resource.\n"
" "
msgstr ""
"\n"
"Modul pro řízení zdrojů.\n"
"===============================\n"
"\n"
"Zdroj představuje něco, co může být naplánováno (developer přiřazen k úkolu "
"nebo\n"
"středisko k výrobní zakázce). Tento modul spravuje kalendáře zdrojů\n"
"spojené s každým prostředkem. Spravuje také absence každého zdroje.\n"
" "
#. module: base
#: model:ir.module.module,description:base.module_account_followup
@ -11883,7 +11922,7 @@ msgstr "pracovní postup"
#. module: base
#: view:ir.rule:0
msgid "Read Access Right"
msgstr ""
msgstr "Přístupové právo ke čtení"
#. module: base
#: model:ir.module.module,shortdesc:base.module_analytic_user_function

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:29+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:39+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

File diff suppressed because it is too large Load Diff

View File

@ -12,8 +12,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:31+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:40+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Poedit-Country: GREECE\n"
"X-Poedit-Language: Greek\n"
"X-Poedit-SourceCharset: utf-8\n"

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:37+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:48+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:35+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:46+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:36+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:48+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:37+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:49+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:37+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:48+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:38+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:49+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"Language: \n"
#. module: base

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:37+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:48+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:38+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:50+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:38+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:49+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:38+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:50+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:36+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:29+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:39+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:28+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:37+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -9,8 +9,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:33+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:44+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Poedit-Country: IRAN, ISLAMIC REPUBLIC OF\n"
"X-Poedit-Language: Persian\n"

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:38+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:50+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:30+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:39+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:30+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:40+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
@ -11393,7 +11393,7 @@ msgstr "Islande"
#: model:ir.actions.act_window,name:base.ir_action_window
#: model:ir.ui.menu,name:base.menu_ir_action_window
msgid "Window Actions"
msgstr "Actions de fênetres"
msgstr "Actions de fetres"
#. module: base
#: model:ir.module.module,description:base.module_portal_project_issue

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:37+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:48+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:30+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:40+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:31+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:41+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

File diff suppressed because it is too large Load Diff

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:31+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:41+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:34+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:45+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"Language: hr\n"
#. module: base

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:31+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:41+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -9,8 +9,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:28+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:37+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:31+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:42+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
@ -58,7 +58,7 @@ msgstr ""
#: field:ir.ui.view,arch:0
#: field:ir.ui.view.custom,arch:0
msgid "View Architecture"
msgstr "Arsitektur View"
msgstr "Lihat Arsitektur"
#. module: base
#: model:ir.module.module,summary:base.module_sale_stock
@ -86,13 +86,13 @@ msgid ""
"Helps you manage your projects and tasks by tracking them, generating "
"plannings, etc..."
msgstr ""
"Memungkinkan Anda untuk mengelola proyek dan tugas dengan cara melacaknya, "
"menghasilkan perencanaan dan lain sebagainya ..."
"Membantu anda mengelola proyek dan tugas dengan cara melacak, menghasilkan "
"perencanaan, dan lain sebagainya..."
#. module: base
#: model:ir.module.module,summary:base.module_point_of_sale
msgid "Touchscreen Interface for Shops"
msgstr "Antarmuka layar sentuh untuk digunakan di toko"
msgstr "Antarmuka Layar Sentuh untuk Toko"
#. module: base
#: model:ir.module.module,shortdesc:base.module_l10n_in_hr_payroll
@ -104,12 +104,12 @@ msgstr "Payroll untuk India"
msgid ""
"Model name on which the method to be called is located, e.g. 'res.partner'."
msgstr ""
"Sebutkan nama model yang mana metode ini akan dipanggil, misal 'res.partner'."
"Nama model dimana terletak metode yang akan dipanggil, contoh 'res.partner'."
#. module: base
#: view:ir.module.module:0
msgid "Created Views"
msgstr "View yang diciptakan"
msgstr "Tampilan yang Diciptakan"
#. module: base
#: model:ir.module.module,description:base.module_product_manufacturer
@ -127,17 +127,17 @@ msgid ""
" "
msgstr ""
"\n"
"Modul ini berfungsi untuk menambahkan nama produsen beserta atributnya pada "
"Sebuah modul yang berfungsi menambahkan nama produsen dan keterangan pada "
"formulir produk.\n"
"============================================================================="
"==\n"
"=====\n"
"\n"
"Anda dapat mengisi data-data berikut pada produk:\n"
"------------------------------------------------\n"
"* Nama produsen\n"
"* Nama produk produsen\n"
"* Code produk produsen\n"
"* Atribut produk\n"
"Anda sekarang dapat menentukan data berikut untuk sebuah produk:\n"
"-------------------------------------------------------------------\n"
" * Produsen\n"
" * Nama Produk Produsen\n"
" * Kode Produk Produsen\n"
" * Keterangan Produk\n"
" "
#. module: base
@ -153,8 +153,8 @@ msgid ""
"========================================\n"
msgstr ""
"\n"
"Modul ini akan menambahkan google user dalam obyek res.user\n"
"====================================================\n"
"Modul ini menambahkan pengguna google dalam res user.\n"
"======================================================\n"
#. module: base
#: help:res.partner,employee:0

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:31+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:41+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:32+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:42+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:32+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:42+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
@ -480,7 +480,7 @@ msgstr ""
#. module: base
#: field:ir.model.relation,name:0
msgid "Relation Name"
msgstr ""
msgstr "リレーション名"
#. module: base
#: view:ir.rule:0
@ -976,7 +976,7 @@ msgstr "ジンバブエ"
#: help:ir.model.constraint,type:0
msgid ""
"Type of the constraint: `f` for a foreign key, `u` for other constraints."
msgstr ""
msgstr "制約のタイプ:`f`は外部キー、`u`は他の制約"
#. module: base
#: view:ir.actions.report.xml:0
@ -1105,7 +1105,7 @@ msgstr "アンドラ公国"
#. module: base
#: field:ir.rule,perm_read:0
msgid "Apply for Read"
msgstr ""
msgstr "読み込みに適用"
#. module: base
#: model:res.country,name:base.mn
@ -1322,7 +1322,7 @@ msgstr "貢献者"
#. module: base
#: field:ir.rule,perm_unlink:0
msgid "Apply for Delete"
msgstr ""
msgstr "削除に適用"
#. module: base
#: selection:ir.property,type:0
@ -1420,7 +1420,7 @@ msgstr "テスト"
#. module: base
#: field:ir.actions.report.xml,attachment:0
msgid "Save as Attachment Prefix"
msgstr ""
msgstr "添付ファイルのプリフィックスとして保存"
#. module: base
#: field:ir.ui.view_sc,res_id:0
@ -1718,7 +1718,7 @@ msgstr "見積り要求や仕入先請求書といった発注関係のプロセ
#. module: base
#: help:res.partner,website:0
msgid "Website of Partner or Company"
msgstr ""
msgstr "取引先または会社のWebサイト"
#. module: base
#: help:base.language.install,overwrite:0
@ -1792,6 +1792,9 @@ msgid ""
"Launch Manually Once: after having been launched manually, it sets "
"automatically to Done."
msgstr ""
"手動:手動で起動します。\n"
"自動:システムを再設定するたびに実行します。\n"
"手動でいったん起動:手動で起動した後は自動に設定されます。"
#. module: base
#: field:res.partner,image_small:0
@ -1936,7 +1939,7 @@ msgstr "読み込みアクセス"
#. module: base
#: help:ir.attachment,res_id:0
msgid "The record id this is attached to"
msgstr ""
msgstr "これに添付するレコードID"
#. module: base
#: model:ir.module.module,description:base.module_share
@ -1969,7 +1972,7 @@ msgstr "企業の処理"
msgid ""
"Check this box if this contact is a supplier. If it's not checked, purchase "
"people will not see it when encoding a purchase order."
msgstr ""
msgstr "連絡先が仕入先の場合はこのボックスをチェックします。チェックしない場合、発注書を作成する際に表示されません。"
#. module: base
#: model:ir.module.module,shortdesc:base.module_hr_evaluation
@ -2255,7 +2258,7 @@ msgstr "バハマ"
#. module: base
#: field:ir.rule,perm_create:0
msgid "Apply for Create"
msgstr ""
msgstr "作成に適用"
#. module: base
#: model:ir.module.category,name:base.module_category_tools
@ -2277,7 +2280,7 @@ msgstr "アイルランド"
msgid ""
"Appears by default on the top right corner of your printed documents (report "
"header)."
msgstr ""
msgstr "印刷された文書(レポートヘッダ)の右上隅にデフォルトで表示されます。"
#. module: base
#: field:base.module.update,update:0
@ -2509,7 +2512,7 @@ msgstr ""
msgid ""
"View type: Tree type to use for the tree view, set to 'tree' for a "
"hierarchical tree view, or 'form' for a regular list view"
msgstr ""
msgstr "ビュータイプ:ツリー表示に使用する型式、階層ツリー表示のための「ツリー」または通常のリスト表示のための「フォーム」に設定"
#. module: base
#: sql_constraint:ir.ui.view_sc:0
@ -3280,7 +3283,7 @@ msgstr "スウェーデン"
#. module: base
#: field:ir.actions.report.xml,report_file:0
msgid "Report File"
msgstr ""
msgstr "レポートファイル"
#. module: base
#: selection:ir.actions.act_window.view,view_mode:0
@ -3595,7 +3598,7 @@ msgstr ""
#. module: base
#: field:base.language.export,modules:0
msgid "Modules To Export"
msgstr ""
msgstr "エクスポートするモジュール"
#. module: base
#: model:res.country,name:base.mt
@ -3855,7 +3858,7 @@ msgstr "トーゴ"
#: field:ir.actions.act_window,res_model:0
#: field:ir.actions.client,res_model:0
msgid "Destination Model"
msgstr ""
msgstr "宛先モデル"
#. module: base
#: selection:ir.sequence,implementation:0
@ -4202,7 +4205,7 @@ msgstr ""
#. module: base
#: model:ir.actions.server,name:base.action_run_ir_action_todo
msgid "Run Remaining Action Todo"
msgstr ""
msgstr "Todoアクションの残りを実行"
#. module: base
#: field:res.partner,ean13:0
@ -4988,7 +4991,7 @@ msgstr ""
#. module: base
#: help:ir.attachment,res_model:0
msgid "The database object this attachment will be attached to"
msgstr ""
msgstr "この添付ファイルに添付されるデータベースオブジェクト"
#. module: base
#: code:addons/base/ir/ir_fields.py:327
@ -5122,7 +5125,7 @@ msgstr "保存"
#. module: base
#: field:ir.actions.report.xml,report_xml:0
msgid "XML Path"
msgstr ""
msgstr "XMLパス"
#. module: base
#: model:res.country,name:base.bj
@ -5519,7 +5522,7 @@ msgstr "ブーベ島"
#. module: base
#: field:ir.model.constraint,type:0
msgid "Constraint Type"
msgstr ""
msgstr "制約タイプ"
#. module: base
#: field:res.company,child_ids:0
@ -5658,7 +5661,7 @@ msgstr ""
#. module: base
#: model:res.groups,name:base.group_sale_salesman_all_leads
msgid "See all Leads"
msgstr ""
msgstr "全ての見込み客を参照"
#. module: base
#: model:res.country,name:base.ci
@ -5684,7 +5687,7 @@ msgstr "リソース名"
#. module: base
#: model:ir.ui.menu,name:base.menu_ir_filters
msgid "User-defined Filters"
msgstr ""
msgstr "ユーザ定義のフィルタ"
#. module: base
#: field:ir.actions.act_window_close,name:0
@ -6074,6 +6077,8 @@ msgid ""
"deleting it (if you delete a native record rule, it may be re-created when "
"you reload the module."
msgstr ""
"アクティブなフィールドのチェックを外すと、レコードのルールを削除せずに無効化します(レコードのルールを削除すると、モジュールを再ロードするときに再作成され"
"ます)。"
#. module: base
#: selection:base.language.install,lang:0
@ -6237,7 +6242,7 @@ msgstr ""
#: help:res.country.state,name:0
msgid ""
"Administrative divisions of a country. E.g. Fed. State, Departement, Canton"
msgstr ""
msgstr "国の行政区画。たとえば連邦、省、州。"
#. module: base
#: view:res.partner.bank:0
@ -6257,12 +6262,12 @@ msgstr "このルールにより影響を受けたオブジェクト"
#. module: base
#: selection:ir.actions.act_window,target:0
msgid "Inline View"
msgstr ""
msgstr "インラインビュー"
#. module: base
#: field:ir.filters,is_default:0
msgid "Default filter"
msgstr ""
msgstr "デフォルトのフィルタ"
#. module: base
#: report:ir.module.reference:0
@ -6630,7 +6635,7 @@ msgstr "世紀なしの現在年: %(y)s"
#: view:ir.config_parameter:0
#: model:ir.ui.menu,name:base.ir_config_menu
msgid "System Parameters"
msgstr ""
msgstr "システムパラメータ"
#. module: base
#: help:ir.actions.client,tag:0
@ -6805,7 +6810,7 @@ msgstr "ランドスケープレポート用RML内部ヘッダ"
#. module: base
#: model:res.groups,name:base.group_partner_manager
msgid "Contact Creation"
msgstr ""
msgstr "連絡先作成"
#. module: base
#: view:ir.module.module:0
@ -7083,7 +7088,7 @@ msgstr "モジュールファイルのインポートが成功しました。"
#: view:ir.model.constraint:0
#: model:ir.ui.menu,name:base.ir_model_constraint_menu
msgid "Model Constraints"
msgstr ""
msgstr "モデル制約"
#. module: base
#: model:ir.actions.act_window,name:base.action_workflow_transition_form
@ -7198,7 +7203,7 @@ msgstr "のコピー"
#. module: base
#: field:ir.model.data,display_name:0
msgid "Record Name"
msgstr ""
msgstr "レコード名"
#. module: base
#: model:ir.model,name:base.model_ir_actions_client
@ -7214,7 +7219,7 @@ msgstr "イギリス領インド洋地域"
#. module: base
#: model:ir.actions.server,name:base.action_server_module_immediate_install
msgid "Module Immediate Install"
msgstr ""
msgstr "モジュール即時インストール"
#. module: base
#: view:ir.actions.server:0
@ -7565,6 +7570,8 @@ msgid ""
"use the same timezone that is otherwise used to pick and render date and "
"time values: your computer's timezone."
msgstr ""
"取引先のタイムゾーン。印刷するレポート内に適切な日付と時刻を出力するために使用します。このフィールドに値を設定することは重要です。日付と時刻を選択して表示"
"するのでなければ、あなたのコンピュータと同じタイムゾーンを使用すべきです。"
#. module: base
#: model:ir.module.module,shortdesc:base.module_account_analytic_default
@ -7633,7 +7640,7 @@ msgstr ""
#. module: base
#: view:ir.rule:0
msgid "Rule Definition (Domain Filter)"
msgstr ""
msgstr "ルール定義(ドメインフィルタ)"
#. module: base
#: selection:ir.actions.act_url,target:0
@ -8340,7 +8347,7 @@ msgstr ""
#. module: base
#: help:ir.model.relation,name:0
msgid "PostgreSQL table name implementing a many2many relation."
msgstr ""
msgstr "多対多の関係を実装するPostgreSQLのテーブル名。"
#. module: base
#: model:ir.module.module,description:base.module_base
@ -8441,7 +8448,7 @@ msgstr "常時検索可能"
#. module: base
#: help:res.country.state,code:0
msgid "The state code in max. three chars."
msgstr ""
msgstr "最大3文字の州コード。"
#. module: base
#: model:res.country,name:base.hk
@ -8604,7 +8611,7 @@ msgstr "ドミニカ"
#. module: base
#: field:ir.translation,name:0
msgid "Translated field"
msgstr ""
msgstr "翻訳フィールド"
#. module: base
#: model:ir.module.module,shortdesc:base.module_stock_location
@ -8682,7 +8689,7 @@ msgstr "アクション結合"
msgid ""
"If the selected language is loaded in the system, all documents related to "
"this contact will be printed in this language. If not, it will be English."
msgstr ""
msgstr "選択された言語がシステムにロードされている場合、この連絡先に関連するすべての文書はこの言語で印刷されます。そうでない場合は英語です。"
#. module: base
#: model:ir.module.module,description:base.module_hr_evaluation
@ -8839,7 +8846,7 @@ msgstr ""
msgid ""
"This field specifies whether the model is transient or not (i.e. if records "
"are automatically deleted from the database or not)"
msgstr ""
msgstr "このフィールドはモデルが一時的かどうか(レコードがデータベースから自動的に削除されるかどうか)を指定します。"
#. module: base
#: code:addons/base/ir/ir_mail_server.py:445
@ -9231,7 +9238,7 @@ msgstr ""
#. module: base
#: model:ir.module.category,name:base.module_category_warehouse_management
msgid "Warehouse"
msgstr ""
msgstr "倉庫"
#. module: base
#: field:ir.exports,resource:0
@ -9568,7 +9575,7 @@ msgstr "%H - 時24時間表示[00,23]."
#. module: base
#: field:ir.model.fields,on_delete:0
msgid "On Delete"
msgstr ""
msgstr "削除時"
#. module: base
#: code:addons/base/ir/ir_model.py:347
@ -9825,7 +9832,7 @@ msgstr "通貨コードは会社ごとに固有でなければいけません。
#: code:addons/base/module/wizard/base_export_language.py:39
#, python-format
msgid "New Language (Empty translation template)"
msgstr ""
msgstr "新しい言語 (空の翻訳テンプレート)"
#. module: base
#: help:ir.actions.server,email:0
@ -10296,7 +10303,7 @@ msgstr "ファイルの内容"
#: view:ir.model.relation:0
#: model:ir.ui.menu,name:base.ir_model_relation_menu
msgid "ManyToMany Relations"
msgstr ""
msgstr "多対多の関係"
#. module: base
#: model:res.country,name:base.pa
@ -10400,7 +10407,7 @@ msgstr "OpenERPは自動的に次の番号に要求されているサイズに
#. module: base
#: help:ir.model.constraint,name:0
msgid "PostgreSQL constraint or foreign key name."
msgstr ""
msgstr "PostgreSQLの制約や外部キーの名前。"
#. module: base
#: view:res.company:0
@ -10425,7 +10432,7 @@ msgstr "ギニアビサウ"
#. module: base
#: field:ir.actions.report.xml,header:0
msgid "Add RML Header"
msgstr ""
msgstr "RMLヘッダを追加"
#. module: base
#: help:res.company,rml_footer:0
@ -10547,7 +10554,7 @@ msgstr "イタリア"
#. module: base
#: model:res.groups,name:base.group_sale_salesman
msgid "See Own Leads"
msgstr ""
msgstr "自分の見込み客を参照"
#. module: base
#: view:ir.actions.todo:0
@ -11057,7 +11064,7 @@ msgstr "オフィス用品"
#. module: base
#: field:ir.attachment,res_model:0
msgid "Resource Model"
msgstr ""
msgstr "リソースモデル"
#. module: base
#: code:addons/custom.py:555
@ -11184,7 +11191,7 @@ msgstr ""
#: model:ir.actions.act_window,name:base.action_inventory_form
#: model:ir.ui.menu,name:base.menu_action_inventory_form
msgid "Default Company per Object"
msgstr ""
msgstr "オブジェクトごとのデフォルト会社"
#. module: base
#: model:ir.module.module,shortdesc:base.module_web_hello
@ -11229,7 +11236,7 @@ msgstr "州名"
#. module: base
#: help:ir.attachment,type:0
msgid "Binary File or URL"
msgstr ""
msgstr "バイナリファイルまたはURL"
#. module: base
#: code:addons/base/ir/ir_fields.py:313
@ -11374,7 +11381,7 @@ msgstr ""
#. module: base
#: field:workflow.transition,signal:0
msgid "Signal (Button Name)"
msgstr ""
msgstr "シグナル(ボタン名)"
#. module: base
#: view:ir.actions.act_window:0
@ -11404,7 +11411,7 @@ msgstr "グレナダ"
#. module: base
#: help:res.partner,customer:0
msgid "Check this box if this contact is a customer."
msgstr ""
msgstr "連絡先が顧客の場合はこのボックスをチェックします。"
#. module: base
#: view:ir.actions.server:0
@ -11439,7 +11446,7 @@ msgstr ""
#. module: base
#: field:res.users,partner_id:0
msgid "Related Partner"
msgstr ""
msgstr "関連取引先"
#. module: base
#: code:addons/osv.py:172
@ -11719,6 +11726,7 @@ msgid ""
"(if you delete a native ACL, it will be re-created when you reload the "
"module."
msgstr ""
"アクティブなフィールドのチェックを外すと、ACLを削除せずに無効化します(ACLを削除すると、モジュールを再ロードするときに再作成されます)。"
#. module: base
#: model:ir.model,name:base.model_ir_fields_converter
@ -12185,7 +12193,7 @@ msgstr "見積書、販売注文書、請求書の処理に役立ちます。"
#. module: base
#: field:res.users,login_date:0
msgid "Latest connection"
msgstr ""
msgstr "最後の接続"
#. module: base
#: field:res.groups,implied_ids:0
@ -12349,7 +12357,7 @@ msgstr "デフォルト値、またはアクションへの参照"
#. module: base
#: field:ir.actions.report.xml,auto:0
msgid "Custom Python Parser"
msgstr ""
msgstr "特注のPythonパーサ"
#. module: base
#: sql_constraint:res.groups:0
@ -12933,7 +12941,7 @@ msgstr "ニューカレドニア(フランス領)"
#. module: base
#: field:ir.model,osv_memory:0
msgid "Transient Model"
msgstr ""
msgstr "過度的なモデル"
#. module: base
#: model:res.country,name:base.cy
@ -13073,7 +13081,7 @@ msgstr "送信メールサーバ"
#. module: base
#: model:ir.ui.menu,name:base.menu_custom
msgid "Technical"
msgstr ""
msgstr "技術"
#. module: base
#: model:res.country,name:base.cn
@ -13290,7 +13298,7 @@ msgstr "起動するアクション"
#: field:ir.model,modules:0
#: field:ir.model.fields,modules:0
msgid "In Modules"
msgstr ""
msgstr "モジュールリスト"
#. module: base
#: model:ir.module.module,shortdesc:base.module_contacts
@ -13783,7 +13791,7 @@ msgstr ""
msgid ""
"Check this to define the report footer manually. Otherwise it will be "
"filled in automatically."
msgstr ""
msgstr "レポートフッタをマニュアルで定義する場合はチェックしてください。それ以外は自動で入力されます。"
#. module: base
#: view:res.partner:0
@ -13829,7 +13837,7 @@ msgstr "ソース"
#: field:ir.model.constraint,date_init:0
#: field:ir.model.relation,date_init:0
msgid "Initialization Date"
msgstr ""
msgstr "初期化の日付"
#. module: base
#: model:res.country,name:base.vu
@ -13998,7 +14006,7 @@ msgstr "複数ドキュメントのアクション"
#: model:ir.actions.act_window,name:base.action_partner_title_partner
#: model:ir.ui.menu,name:base.menu_partner_title_partner
msgid "Titles"
msgstr ""
msgstr "敬称"
#. module: base
#: model:ir.module.module,description:base.module_anonymization
@ -14298,7 +14306,7 @@ msgstr "ヘルプデスク"
#. module: base
#: field:ir.rule,perm_write:0
msgid "Apply for Write"
msgstr ""
msgstr "読み込みに適用"
#. module: base
#: field:ir.ui.menu,parent_left:0
@ -14456,7 +14464,7 @@ msgstr "ペルシア語 / فارس"
#. module: base
#: view:base.language.export:0
msgid "Export Settings"
msgstr ""
msgstr "エクスポート設定"
#. module: base
#: field:ir.actions.act_window,src_model:0
@ -15333,7 +15341,7 @@ msgstr ""
#. module: base
#: field:ir.model.data,complete_name:0
msgid "Complete ID"
msgstr ""
msgstr "完了ID"
#. module: base
#: model:ir.module.module,description:base.module_stock
@ -15488,7 +15496,7 @@ msgstr "購買依頼"
#. module: base
#: selection:ir.actions.act_window,target:0
msgid "Inline Edit"
msgstr ""
msgstr "インライン編集"
#. module: base
#: selection:ir.cron,interval_type:0

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:30+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:40+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:32+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:42+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:32+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:42+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:32+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:43+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:32+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:43+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:33+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:43+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:33+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:43+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
@ -14808,6 +14808,15 @@ msgid ""
"automatically new claims based on incoming emails.\n"
" "
msgstr ""
"\n"
"\n"
"Захиалагчийн Гомдлын Менежмент.\n"
"=======================\n"
"Энэ аппликэйшн нь захиалагч/нийлүүлэгчийн гомдлыг хөтлөх боломжийг олгодог.\n"
"\n"
"Энэ модуль нь эмэйл үүдтэй бүрэн уялддаг тул ирж буй имэйлээс\n"
"автоматаар гомдлыг үүсгэх боломжтой.\n"
" "
#. module: base
#: model:ir.module.module,shortdesc:base.module_account_test

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:33+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:43+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:29+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:39+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:37+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:48+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:33+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:44+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:33+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:44+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:36+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:34+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:44+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
@ -26,7 +26,7 @@ msgid ""
msgstr ""
"\n"
"Modul pentru Bifeaza Scriere si Bifeaza Imprimare.\n"
"================================================\n"
"==================================================\n"
" "
#. module: base
@ -129,7 +129,7 @@ msgid ""
msgstr ""
"\n"
"Un modul care adauga producatori si atribute la formularul produsului.\n"
"====================================================================\n"
"======================================================================\n"
"\n"
"Acum puteti defini urmatoarele pentru un produs:\n"
"-----------------------------------------------\n"
@ -153,7 +153,7 @@ msgid ""
msgstr ""
"\n"
"Acest modul adauga utilizatorul google la utilizatorul res.\n"
"========================================\n"
"===========================================================\n"
#. module: base
#: help:res.partner,employee:0
@ -212,7 +212,7 @@ msgid ""
msgstr ""
"\n"
"Generează Facturi din Cheltuieli, Înregistrări ale Fișelor de Pontaj.\n"
"========================================================\n"
"=====================================================================\n"
"\n"
"Modul pentru generarea facturilor pe baza costurilor (resurse umane, "
"cheltuieli, ...).\n"
@ -249,7 +249,7 @@ msgstr "Eroare constrângere"
#. module: base
#: model:ir.model,name:base.model_ir_ui_view_custom
msgid "ir.ui.view.custom"
msgstr "ir.ui.vizualizare.personalizata"
msgstr "ir.ui.view.custom"
#. module: base
#: code:addons/base/ir/ir_model.py:374
@ -405,7 +405,7 @@ msgid ""
msgstr ""
"\n"
"Programul de instalare Ascuns bazat pe cunostinte.\n"
"=====================================\n"
"==================================================\n"
"\n"
"Face Configuratia Aplicatiei Cunostinte disponibila, de unde puteti instala\n"
"documente si Ascuns bazat pe Wiki.\n"
@ -617,7 +617,7 @@ msgid ""
msgstr ""
"\n"
"Modul pentru definirea obiectului contabilitatii analitice.\n"
"===============================================\n"
"=========================================================\n"
"\n"
"In OpenERP, conturile analitice sunt legate de conturile generale, dar sunt "
"tratate\n"
@ -650,7 +650,7 @@ msgid ""
msgstr ""
"\n"
"Organizarea si gestionarea Evenimentelor.\n"
"======================================\n"
"=========================================\n"
"\n"
"Modulul eveniment va permite sa organizati eficient evenimente si toate "
"sarcinile asociate lor: planificare, urmarirea inregistrarii,\n"
@ -950,7 +950,7 @@ msgstr "Data urmatoarei executii planificate pentru aceasta sarcina."
#. module: base
#: model:ir.model,name:base.model_ir_ui_view
msgid "ir.ui.view"
msgstr "ir.ui.vizualizare"
msgstr "ir.ui.view"
#. module: base
#: model:res.country,name:base.er
@ -975,7 +975,7 @@ msgstr "România - Contabilitate"
#. module: base
#: model:ir.model,name:base.model_res_config_settings
msgid "res.config.settings"
msgstr "res.configurare.setari"
msgstr "res.config.settings"
#. module: base
#: help:res.partner,image_small:0
@ -996,8 +996,8 @@ msgid ""
"the correct mobile number"
msgstr ""
"Furnizeaza campurile care sunt folosite pentru a cauta numarul de telefon "
"mobil, de exemplu dumneavoastra selectati factura, atunci "
"`obiect.factura_adresa_id.mobil` este campul care va da numarul corect de "
"mobil, de exemplu dumneavoastra selectati factura, atunci "
"`object.invoice_address_id.mobile` este campul care va da numarul corect de "
"telefon mobil"
#. module: base
@ -1932,7 +1932,7 @@ msgstr "Sfantul Martin (partea franceza)"
#. module: base
#: model:ir.model,name:base.model_ir_exports
msgid "ir.exports"
msgstr "ir.exporturi"
msgstr "ir.exports"
#. module: base
#: model:ir.module.module,description:base.module_l10n_lu
@ -2056,7 +2056,7 @@ msgstr "Bancă"
#. module: base
#: model:ir.model,name:base.model_ir_exports_line
msgid "ir.exports.line"
msgstr "ir.linie.exporturi"
msgstr "ir.exports.line"
#. module: base
#: model:ir.module.category,description:base.module_category_purchase_management
@ -2125,8 +2125,8 @@ msgid ""
"Access all the fields related to the current object using expressions, i.e. "
"object.partner_id.name "
msgstr ""
"Acceseaza toate fisierele asociate obiectului actual folosind expresii, de "
"exemplu obiect.partener_id.nume "
"Accesează toate câmpurile asociate obiectului actual folosind expresii, de "
"exemplu object.partner_id.name "
#. module: base
#: model:ir.module.module,shortdesc:base.module_portal_project_issue
@ -2169,7 +2169,7 @@ msgstr "Gestiunea depozitului"
#. module: base
#: model:ir.model,name:base.model_res_request_link
msgid "res.request.link"
msgstr "res.link.cerere"
msgstr "res.request.link"
#. module: base
#: field:ir.actions.wizard,name:0
@ -2260,7 +2260,7 @@ msgstr ""
#. module: base
#: view:ir.sequence:0
msgid "Day: %(day)s"
msgstr "Ziua: %(zi)s"
msgstr "Ziua: %(day)s"
#. module: base
#: model:ir.module.category,description:base.module_category_point_of_sale
@ -2299,7 +2299,7 @@ msgstr "Traducere în desfășurare"
#. module: base
#: model:ir.model,name:base.model_ir_rule
msgid "ir.rule"
msgstr "ir.regula"
msgstr "ir.rule"
#. module: base
#: selection:ir.cron,interval_type:0
@ -2456,7 +2456,7 @@ msgstr ""
#. module: base
#: model:ir.model,name:base.model_ir_model_access
msgid "ir.model.access"
msgstr "ir.model.acces"
msgstr "ir.model.access"
#. module: base
#: model:ir.module.module,description:base.module_l10n_multilang
@ -2987,7 +2987,7 @@ msgstr "Va fi șters"
#. module: base
#: model:ir.model,name:base.model_ir_sequence
msgid "ir.sequence"
msgstr "ir.secventa"
msgstr "ir.sequence"
#. module: base
#: help:ir.actions.server,expression:0
@ -2996,9 +2996,9 @@ msgid ""
"order in Object, and you can have loop on the sales order line. Expression = "
"`object.order_line`."
msgstr ""
"Introduceti campul/expresia care va genera lista. De exemplu, selectati "
"comanda de vanzare in Obiect, si puteti parcurge in bucla pozitiile din "
"comanda de vanzare. Expresie = `obiect.linie_comanda`."
"Introduceți câmpul / expresia care sa genereze lista. De exemplu, selectând "
"comanda de vânzare în Obiecte puteți parcurge în buclă pozițiile din "
"comandă. Expresie = `object.order_line`."
#. module: base
#: field:ir.mail_server,smtp_debug:0
@ -3591,7 +3591,7 @@ msgstr ""
#. module: base
#: model:ir.model,name:base.model_ir_actions_act_window_close
msgid "ir.actions.act_window_close"
msgstr "ir.actiuni.inchide_fereastra_act"
msgstr "ir.actions.act_window_close"
#. module: base
#: field:ir.server.object.lines,col1:0
@ -4878,7 +4878,7 @@ msgstr "Jersey"
#. module: base
#: model:ir.model,name:base.model_ir_translation
msgid "ir.translation"
msgstr "ir.traducere"
msgstr "ir.translation"
#. module: base
#: view:res.lang:0
@ -4954,7 +4954,7 @@ msgstr "Reg"
#. module: base
#: model:ir.model,name:base.model_ir_property
msgid "ir.property"
msgstr "ir.proprietate"
msgstr "ir.property"
#. module: base
#: selection:ir.actions.act_window,view_type:0
@ -6083,9 +6083,9 @@ msgid ""
"the same values as those available in the condition field, e.g. `Dear [[ "
"object.partner_id.name ]]`"
msgstr ""
"Continuturile e-mail-urilor, pot sa contina expresii incluse in paranteze "
"duble bazate pe aceleasi valori ca si cele disponibile in campul conditie, "
"de exemplu: `Stimate [[ obiect.id_nume.partener ]]`"
"Conținuturile e-mail-urilor, pot sa includă expresii incluse în paranteze "
"duble bazate pe aceleași valori ca și cele disponibile în câmpul condiție, "
"de exemplu: `Stimate [[ object.partner_id.name ]]`"
#. module: base
#: model:ir.actions.act_window,name:base.action_workflow_form
@ -6329,7 +6329,7 @@ msgstr "Nume de utilizator optional pentru autentificarea SMTP"
#. module: base
#: model:ir.model,name:base.model_ir_actions_actions
msgid "ir.actions.actions"
msgstr "ir.actiuni.actiuni"
msgstr "ir.actions.actions"
#. module: base
#: selection:ir.model.fields,select_level:0
@ -6364,19 +6364,19 @@ msgid ""
" \n"
"%(country_code)s: the code of the country"
msgstr ""
"Aici puteti mentiona formatul obisnuit care va fi folosit pentru adresele "
"care apartin acestei tari.\n"
"Aici puteți menționa formatul obișnuit care va fi folosit pentru adresele "
"acestei țări.\n"
"\n"
"Puteti folosi tiparul in sir stil python cu toate campurile adreselor (de "
"exemplu, folositi '%(strada)s' pentru a afisa campul 'strada') plus\n"
"Puteți folosi tiparul in sir stil python cu toate câmpurile adreselor (de "
"exemplu, folosiți '%(street)s' pentru a afișa câmpul 'strada') plus\n"
" \n"
"%(nume_stat)s: numele statului\n"
"%(state_name)s: numele statului (județului)\n"
" \n"
"%(cod_stat)s: codul statului\n"
"%(state_code)s: codul statului (județului)\n"
" \n"
"%(nume_tara)s: numele tarii\n"
"%(country_name)s: numele țării\n"
" \n"
"%(cod_tara)s: codul tarii"
"%(country_code)s: codul țării"
#. module: base
#: model:res.country,name:base.mu
@ -7194,7 +7194,7 @@ msgstr ""
#. module: base
#: model:ir.model,name:base.model_ir_actions_act_window_view
msgid "ir.actions.act_window.view"
msgstr "ir.actiuni.act_fereastra.vizualizare"
msgstr "ir.actions.act_window.view"
#. module: base
#: model:ir.module.module,shortdesc:base.module_web
@ -7278,7 +7278,7 @@ msgstr "Insulele Svalbard si Jan Mayen"
#: model:ir.model,name:base.model_ir_actions_wizard
#: selection:ir.ui.menu,action:0
msgid "ir.actions.wizard"
msgstr "ir.asistent.actiuni"
msgstr "ir.actions.wizard"
#. module: base
#: model:ir.module.module,shortdesc:base.module_web_kanban
@ -7567,7 +7567,7 @@ msgstr "Start Flux"
#. module: base
#: model:ir.model,name:base.model_res_partner_title
msgid "res.partner.title"
msgstr "res.partener.titlu"
msgstr "res.partner.title"
#. module: base
#: view:res.partner.bank:0
@ -8097,7 +8097,7 @@ msgstr "Meniuri Create"
#: view:ir.module.module:0
#, python-format
msgid "Uninstall"
msgstr "Dezinstaleaza"
msgstr "Dezinstalați"
#. module: base
#: model:ir.module.module,shortdesc:base.module_account_budget
@ -8208,7 +8208,7 @@ msgstr "Curaçao"
#. module: base
#: view:ir.sequence:0
msgid "Current Year without Century: %(y)s"
msgstr "Anul curent fara Secol: %(y)s"
msgstr "Anul curent fără secol: %(y)s"
#. module: base
#: model:ir.actions.act_window,name:base.ir_config_list_action
@ -8490,7 +8490,7 @@ msgstr ""
#. module: base
#: view:ir.sequence:0
msgid "Week of the Year: %(woy)s"
msgstr "Saptamana din An: %(sda)s"
msgstr "Săptămâna din an: %(woy)s"
#. module: base
#: field:res.users,id:0
@ -8601,7 +8601,7 @@ msgstr "Filtre vizibile doar pentru un utilizator"
#. module: base
#: model:ir.model,name:base.model_ir_attachment
msgid "ir.attachment"
msgstr "ir.atasament"
msgstr "ir.attachment"
#. module: base
#: code:addons/orm.py:4348
@ -9154,7 +9154,7 @@ msgstr ""
#. module: base
#: model:ir.model,name:base.model_ir_config_parameter
msgid "ir.config_parameter"
msgstr "ir.configurare_parametru"
msgstr "ir.config_parameter"
#. module: base
#: model:ir.module.module,description:base.module_project_long_term
@ -9243,7 +9243,7 @@ msgstr "Compania pentru care acest utilizator lucreaza in prezent."
#. module: base
#: model:ir.model,name:base.model_wizard_ir_model_menu_create
msgid "wizard.ir.model.menu.create"
msgstr "wizard.ir.creeaza.model.meniu"
msgstr "wizard.ir.model.menu.create"
#. module: base
#: view:workflow.transition:0
@ -9981,9 +9981,9 @@ msgid ""
"the same values as those available in the condition field, e.g. `Hello [[ "
"object.partner_id.name ]]`"
msgstr ""
"Subiectul e-mail-ului poate sa contina expresii intre paranteze duble, "
"bazate pe aceleasi valori ca si cele disponibile in campul conditie, de ex. "
"`Buna ziua [[obiect.partener_id.nume]]`"
"Subiectul e-mail-ului poate să conțină expresii intre paranteze duble, "
"bazate pe aceleași valori ca și cele disponibile în câmpul condiție, de ex. "
"`Buna ziua [[ object.partner_id.name ]]`"
#. module: base
#: help:res.partner,image:0
@ -10209,7 +10209,7 @@ msgstr "Austria - Contabilitate"
#. module: base
#: model:ir.model,name:base.model_ir_ui_menu
msgid "ir.ui.menu"
msgstr "ir.ui.meniu"
msgstr "ir.ui.menu"
#. module: base
#: model:ir.module.module,shortdesc:base.module_project
@ -10219,7 +10219,7 @@ msgstr "Managementul Proiectelor"
#. module: base
#: view:ir.module.module:0
msgid "Cancel Uninstall"
msgstr "Anulati dezinstalarea"
msgstr "Anulați dezinstalarea"
#. module: base
#: view:res.bank:0
@ -10234,7 +10234,7 @@ msgstr "Contabilitate Analitica"
#. module: base
#: model:ir.model,name:base.model_ir_model_constraint
msgid "ir.model.constraint"
msgstr "ir.restrictie.model"
msgstr "ir.model.constraint"
#. module: base
#: model:ir.module.module,shortdesc:base.module_web_graph
@ -10260,7 +10260,7 @@ msgstr ""
#. module: base
#: model:ir.model,name:base.model_ir_server_object_lines
msgid "ir.server.object.lines"
msgstr "ir.linii.obiect.server"
msgstr "ir.server.object.lines"
#. module: base
#: model:ir.module.module,shortdesc:base.module_l10n_be
@ -10889,7 +10889,7 @@ msgstr "Instalati Actualizare Modul"
#. module: base
#: model:ir.model,name:base.model_ir_actions_configuration_wizard
msgid "ir.actions.configuration.wizard"
msgstr "ir.wizard.configurare.actiuni"
msgstr "ir.actions.configuration.wizard"
#. module: base
#: view:res.lang:0
@ -11835,7 +11835,7 @@ msgstr "Statele Unite - Plan de Conturi"
#: view:res.users:0
#: view:wizard.ir.model.menu.create:0
msgid "Cancel"
msgstr "Anulati"
msgstr "Anulați"
#. module: base
#: code:addons/orm.py:1507
@ -12119,9 +12119,9 @@ msgid ""
"same values as for the condition field.\n"
"Example: object.invoice_address_id.email, or 'me@example.com'"
msgstr ""
"Expresie care intoarce adresa de e-mail la trimite catre. Poate fi bazata pe "
"aceleasi valori ca si pentru campul conditie.\n"
"Exemplu: obiect.id_adresa_factura.e-mail, sau 'me@exemplu.com'"
"Expresie care întoarce adresa de e-mail în câmpul trimite către. Poate fi "
"bazată pe aceleași valori ca și pentru câmpul condiție.\n"
"Exemplu: object.invoice_address_id.email, sau 'me@exemplu.com'"
#. module: base
#: model:ir.module.module,description:base.module_project_issue_sheet
@ -12326,7 +12326,7 @@ msgid ""
" </p>\n"
" "
msgstr ""
"<clasa p=\"creeaza_niciuncontinut_vizualizare_oe\">\n"
"<p class=\"oe_view_nocontent_create\">\n"
" Faceti click pentru a adauga un contact in agenda "
"dumneavoastra.\n"
" </p><p>\n"
@ -12389,7 +12389,7 @@ msgstr "Cod"
#. module: base
#: model:ir.model,name:base.model_res_config_installer
msgid "res.config.installer"
msgstr "res.config.program_de_instalare"
msgstr "res.config.installer"
#. module: base
#: model:res.country,name:base.mc
@ -12452,7 +12452,7 @@ msgstr ""
#. module: base
#: view:ir.sequence:0
msgid "Current Year with Century: %(year)s"
msgstr "Anul curent cu Secol: %(an)s"
msgstr "Anul curent cu secol: %(year)s"
#. module: base
#: field:ir.exports,export_fields:0
@ -12593,7 +12593,7 @@ msgstr "Chineza (TW) / 正體字"
#. module: base
#: model:ir.model,name:base.model_res_request
msgid "res.request"
msgstr "res.cerere"
msgstr "res.request"
#. module: base
#: field:res.partner,image_medium:0
@ -13120,7 +13120,7 @@ msgstr ""
#. module: base
#: model:ir.model,name:base.model_ir_mail_server
msgid "ir.mail_server"
msgstr "ir.server_e-mail"
msgstr "ir.mail_server"
#. module: base
#: selection:base.language.install,lang:0
@ -13689,7 +13689,7 @@ msgstr "Fus orar"
#: model:ir.model,name:base.model_ir_actions_report_xml
#: selection:ir.ui.menu,action:0
msgid "ir.actions.report.xml"
msgstr "ir.actiuni.raport.xml"
msgstr "ir.actions.report.xml"
#. module: base
#: model:ir.actions.act_window,name:base.ir_sequence_form
@ -14248,7 +14248,7 @@ msgstr "Data trimiterii"
#. module: base
#: view:ir.sequence:0
msgid "Month: %(month)s"
msgstr "Luna: %(luna)s"
msgstr "Luna: %(month)s"
#. module: base
#: field:ir.actions.act_window.view,sequence:0
@ -14285,7 +14285,7 @@ msgstr ""
#. module: base
#: model:ir.model,name:base.model_ir_fields_converter
msgid "ir.fields.converter"
msgstr "ir.convertor.campuri"
msgstr "ir.fields.converter"
#. module: base
#: code:addons/base/res/res_partner.py:439
@ -14308,12 +14308,12 @@ msgstr "Comore"
#. module: base
#: view:ir.module.module:0
msgid "Cancel Install"
msgstr "Anulati Instalarea"
msgstr "Anulați Instalarea"
#. module: base
#: model:ir.model,name:base.model_ir_model_relation
msgid "ir.model.relation"
msgstr "ir.model.relatie"
msgstr "ir.model.relation"
#. module: base
#: model:ir.module.module,shortdesc:base.module_account_check_writing
@ -14534,7 +14534,7 @@ msgstr "Planuri Analitice Multiple"
#. module: base
#: model:ir.model,name:base.model_ir_default
msgid "ir.default"
msgstr "ir.implicit"
msgstr "ir.default"
#. module: base
#: view:ir.sequence:0
@ -14633,9 +14633,9 @@ msgstr ""
"*URL:** legatura dumneavoastra moodle, de exemplu: "
"http://openerp.moodle.com\n"
"\n"
"**AUTENTIFICARE:** ${obiect.nume_de_utilizator_moodle}\n"
"**AUTENTIFICARE:**${object.moodle_username}\n"
" \n"
"**PAROLA:** ${obiect.parola_utilizator_moodle}\n"
"**PAROLA:** ${object.moodle_user_password}\n"
#. module: base
#: model:ir.module.module,shortdesc:base.module_l10n_uk
@ -15423,7 +15423,7 @@ msgid ""
msgstr ""
"\n"
"Retele Sociale orientate spre afaceri\n"
"===================================\n"
"=====================================\n"
"Modulul Retele Sociale furnizeaza un strat de abstractizare unificat de "
"retele sociale, permitand aplicatiilor sa afiseze un istoric\n"
"complet al conversatiilor in documente cu un sistem complet integrat de "
@ -15537,7 +15537,7 @@ msgstr ""
#. module: base
#: model:ir.model,name:base.model_ir_values
msgid "ir.values"
msgstr "ir.valori"
msgstr "ir.values"
#. module: base
#: model:ir.model,name:base.model_base_module_update
@ -16201,7 +16201,7 @@ msgstr "Agenda"
#. module: base
#: model:ir.model,name:base.model_ir_sequence_type
msgid "ir.sequence.type"
msgstr "ir.tip.secventa"
msgstr "ir.sequence.type"
#. module: base
#: model:ir.module.module,shortdesc:base.module_l10n_be_hr_payroll_account
@ -16825,7 +16825,7 @@ msgstr "Nu pot exista doi utilizatori cu acelasi nume de autentificare !"
#. module: base
#: model:ir.model,name:base.model_res_request_history
msgid "res.request.history"
msgstr "res.istoric.solicitari"
msgstr "res.request.history"
#. module: base
#: model:ir.model,name:base.model_multi_company_default
@ -17409,7 +17409,7 @@ msgstr "Uzbekistan"
#: model:ir.model,name:base.model_ir_actions_act_window
#: selection:ir.ui.menu,action:0
msgid "ir.actions.act_window"
msgstr "ir.actiuni.act_fereastra"
msgstr "ir.actions.act_window"
#. module: base
#: model:res.country,name:base.vi
@ -17597,7 +17597,7 @@ msgstr "Germania - Contabilitate"
#. module: base
#: view:ir.sequence:0
msgid "Day of the Year: %(doy)s"
msgstr "Ziua din An: %(doy)s"
msgstr "Ziua din an: %(doy)s"
#. module: base
#: field:ir.ui.menu,web_icon:0
@ -17642,7 +17642,7 @@ msgstr "Model sursa"
#. module: base
#: view:ir.sequence:0
msgid "Day of the Week (0:Monday): %(weekday)s"
msgstr "Ziua din Saptamana (0:Luni): %(weekday)s"
msgstr "Ziua din saptămâna (0:Luni): %(weekday)s"
#. module: base
#: code:addons/base/module/wizard/base_module_upgrade.py:84
@ -17936,7 +17936,7 @@ msgstr ""
#. module: base
#: model:ir.model,name:base.model_ir_model_data
msgid "ir.model.data"
msgstr "ir.date.model"
msgstr "ir.model.data"
#. module: base
#: selection:base.language.install,lang:0
@ -18442,7 +18442,7 @@ msgstr "Grafic"
#: model:ir.model,name:base.model_ir_actions_server
#: selection:ir.ui.menu,action:0
msgid "ir.actions.server"
msgstr "ir.actiuni.server"
msgstr "ir.actions.server"
#. module: base
#: model:ir.module.module,shortdesc:base.module_l10n_ca
@ -18953,7 +18953,7 @@ msgstr "Note Interne"
#: model:res.partner.title,name:base.res_partner_title_pvt_ltd
#: model:res.partner.title,shortcut:base.res_partner_title_pvt_ltd
msgid "Corp."
msgstr "Corp."
msgstr "SA"
#. module: base
#: model:ir.module.module,shortdesc:base.module_purchase_requisition

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:34+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:45+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
@ -7386,7 +7386,7 @@ msgstr ""
#. module: base
#: selection:res.currency,position:0
msgid "After Amount"
msgstr "Сумма после налогов"
msgstr "После суммы"
#. module: base
#: selection:base.language.install,lang:0
@ -13474,7 +13474,7 @@ msgstr ""
#. module: base
#: selection:res.currency,position:0
msgid "Before Amount"
msgstr "Предварительный итог"
msgstr "Перед суммой"
#. module: base
#: field:res.request,act_from:0

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:34+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:45+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
@ -25,6 +25,10 @@ msgid ""
"================================================\n"
" "
msgstr ""
"\n"
"Modul pre vypisovanie a tlač šekov.\n"
"================================================\n"
" "
#. module: base
#: model:res.country,name:base.sh

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:34+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:45+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:28+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:37+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:34+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:45+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:39+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:50+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:35+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:46+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:35+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:46+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:35+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:46+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:35+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:46+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:35+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:36+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:36+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:38+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:49+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:36+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:47+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-12-19 05:37+0000\n"
"X-Generator: Launchpad (build 16872)\n"
"X-Launchpad-Export-Date: 2014-02-04 05:49+0000\n"
"X-Generator: Launchpad (build 16916)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -37,6 +37,7 @@ import ir_config_parameter
import osv_memory_autovacuum
import ir_mail_server
import ir_fields
import ir_qweb
import ir_http
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -2,7 +2,7 @@
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2013 OpenERP S.A. <http://www.openerp.com>
# Copyright (C) 2004-2014 OpenERP S.A. <http://www.openerp.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
@ -417,7 +417,7 @@ class ir_actions_server(osv.osv):
def _select_objects(self, cr, uid, context=None):
model_pool = self.pool.get('ir.model')
ids = model_pool.search(cr, uid, [('name', 'not ilike', '.')])
ids = model_pool.search(cr, uid, [], limit=None)
res = model_pool.read(cr, uid, ids, ['model', 'name'])
return [(r['model'], r['name']) for r in res] + [('', '')]
@ -910,11 +910,34 @@ class ir_actions_server(osv.osv):
if action.link_new_record and action.link_field_id:
self.pool[action.model_id.model].write(cr, uid, [context.get('active_id')], {action.link_field_id.name: res_id})
def _get_eval_context(self, cr, uid, action, context=None):
""" Prepare the context used when evaluating python code, like the
condition or code server actions.
:param action: the current server action
:type action: browse record
:returns: dict -- evaluation context given to (safe_)eval """
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
obj_pool = self.pool[action.model_id.model]
obj = None
if context.get('active_model') == action.model_id.model and context.get('active_id'):
obj = obj_pool.browse(cr, uid, context['active_id'], context=context)
return {
'self': obj_pool,
'object': obj,
'obj': obj,
'pool': self.pool,
'time': time,
'cr': cr,
'uid': uid,
'user': user,
}
def run(self, cr, uid, ids, context=None):
""" Run the server action. For each server action, the condition is
checked. Note that A void (aka False) condition is considered as always
""" Runs the server action. For each server action, the condition is
checked. Note that a void (``False``) condition is considered as always
valid. If it is verified, the run_action_<STATE> method is called. This
allows easy inheritance of the server actions.
allows easy overriding of the server actions.
:param dict context: context should contain following keys
@ -932,25 +955,9 @@ class ir_actions_server(osv.osv):
if context is None:
context = {}
res = False
user = self.pool.get('res.users').browse(cr, uid, uid)
active_ids = context.get('active_ids', [context.get('active_id')])
for action in self.browse(cr, uid, ids, context):
obj_pool = self.pool[action.model_id.model]
obj = None
if context.get('active_model') == action.model_id.model and context.get('active_id'):
obj = obj_pool.browse(cr, uid, context['active_id'], context=context)
# evaluation context for python strings to evaluate
eval_context = {
'self': obj_pool,
'object': obj,
'obj': obj,
'pool': self.pool,
'time': time,
'cr': cr,
'uid': uid,
'user': user,
}
eval_context = self._get_eval_context(cr, uid, action, context=context)
condition = action.condition
if condition is False:
# Void (aka False) conditions are considered as True

View File

@ -45,6 +45,7 @@ class ir_attachment(osv.osv):
The default implementation is the file:dirname location that stores files
on the local filesystem using name based on their sha1 hash
"""
_order = 'id desc'
def _name_get_resname(self, cr, uid, ids, object, method, context):
data = {}
for attachment in self.browse(cr, uid, ids, context=context):
@ -242,7 +243,7 @@ class ir_attachment(osv.osv):
# performed in batch as much as possible.
ima = self.pool.get('ir.model.access')
for model, targets in model_attachments.iteritems():
if model not in self.pool:
if not self.pool.get(model):
continue
if not ima.check(cr, uid, model, 'read', False):
# remove all corresponding attachment ids

View File

@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
import cStringIO
import datetime
import functools
import operator
@ -12,6 +13,7 @@ from openerp.osv import orm
from openerp.tools.translate import _
from openerp.tools.misc import DEFAULT_SERVER_DATE_FORMAT,\
DEFAULT_SERVER_DATETIME_FORMAT
from openerp.tools import html_sanitize
REFERENCING_FIELDS = set([None, 'id', '.id'])
def only_ref_fields(record):
@ -128,14 +130,17 @@ class ir_fields_converter(orm.Model):
:param column: column object to generate a value for
:type column: :class:`fields._column`
:param type fromtype: type to convert to something fitting for ``column``
:param fromtype: type to convert to something fitting for ``column``
:type fromtype: type | str
:param context: openerp request context
:return: a function (fromtype -> column.write_type), if a converter is found
:rtype: Callable | None
"""
assert isinstance(fromtype, (type, str))
# FIXME: return None
typename = fromtype.__name__ if isinstance(fromtype, type) else fromtype
converter = getattr(
self, '_%s_to_%s' % (fromtype.__name__, column._type), None)
self, '_%s_to_%s' % (typename, column._type), None)
if not converter: return None
return functools.partial(
@ -184,7 +189,7 @@ class ir_fields_converter(orm.Model):
def _str_id(self, cr, uid, model, column, value, context=None):
return value, []
_str_to_reference = _str_to_char = _str_to_text = _str_to_binary = _str_id
_str_to_reference = _str_to_char = _str_to_text = _str_to_binary = _str_to_html = _str_id
def _str_to_date(self, cr, uid, model, column, value, context=None):
try:

View File

@ -15,9 +15,7 @@ from openerp.osv import osv, orm
_logger = logging.getLogger(__name__)
# FIXME: replace by proxy on request.uid?
_uid = object()
UID_PLACEHOLDER = object()
class ModelConverter(werkzeug.routing.BaseConverter):
@ -29,7 +27,7 @@ class ModelConverter(werkzeug.routing.BaseConverter):
def to_python(self, value):
m = re.match(self.regex, value)
return request.registry[self.model].browse(
request.cr, _uid, int(m.group(1)), context=request.context)
request.cr, UID_PLACEHOLDER, int(m.group(1)), context=request.context)
def to_url(self, value):
return value.id
@ -43,10 +41,7 @@ class ModelsConverter(werkzeug.routing.BaseConverter):
self.regex = '([0-9,]+)'
def to_python(self, value):
# TODO:
# - raise routing.ValidationError() if no browse record can be createdm
# - support slug
return request.registry[self.model].browse(request.cr, _uid, [int(i) for i in value.split(',')], context=request.context)
return request.registry[self.model].browse(request.cr, UID_PLACEHOLDER, [int(i) for i in value.split(',')], context=request.context)
def to_url(self, value):
return ",".join(i.id for i in value)
@ -66,15 +61,15 @@ class ir_http(osv.AbstractModel):
if not request.uid:
raise http.SessionExpiredException("Session expired")
def _auth_method_admin(self):
if not request.db:
raise http.SessionExpiredException("No valid database for request %s" % request.httprequest)
request.uid = openerp.SUPERUSER_ID
def _auth_method_none(self):
request.disable_db = True
request.uid = None
def _auth_method_public(self):
if not request.session.uid:
dummy, request.uid = self.pool['ir.model.data'].get_object_reference(request.cr, openerp.SUPERUSER_ID, 'base', 'public_user')
else:
request.uid = request.session.uid
def _authenticate(self, auth_method='user'):
if request.session.uid:
try:
@ -88,16 +83,8 @@ class ir_http(osv.AbstractModel):
return auth_method
def _handle_exception(self, exception):
if isinstance(exception, openerp.exceptions.AccessError):
code = 403
else:
code = getattr(exception, 'code', 500)
fn = getattr(self, '_handle_%d' % code, self._handle_unknown_exception)
return fn(exception)
def _handle_unknown_exception(self, exception):
raise exception
# If handle exception return something different than None, it will be used as a response
raise
def _dispatch(self):
# locate the controller method
@ -108,17 +95,17 @@ class ir_http(osv.AbstractModel):
# check authentication level
try:
auth_method = self._authenticate(getattr(func, "auth", None))
auth_method = self._authenticate(func.routing["auth"])
except Exception:
# force a Forbidden exception with the original traceback
return self._handle_exception(
convert_exception_to(
werkzeug.exceptions.Forbidden))
# post process arg to set uid on browse records
for arg in arguments.itervalues():
if isinstance(arg, orm.browse_record) and arg._uid is _uid:
arg._uid = request.uid
processing = self._postprocess_args(arguments)
if processing:
return processing
# set and execute handler
try:
@ -131,6 +118,16 @@ class ir_http(osv.AbstractModel):
return result
def _postprocess_args(self, arguments):
""" post process arg to set uid on browse records """
for arg in arguments.itervalues():
if isinstance(arg, orm.browse_record) and arg._uid is UID_PLACEHOLDER:
arg._uid = request.uid
try:
arg[arg._rec_name]
except KeyError:
return self._handle_exception(werkzeug.exceptions.NotFound())
def routing_map(self):
if not hasattr(self, '_routing_map'):
_logger.info("Generating routing map")
@ -138,7 +135,7 @@ class ir_http(osv.AbstractModel):
m = request.registry.get('ir.module.module')
ids = m.search(cr, openerp.SUPERUSER_ID, [('state', '=', 'installed'), ('name', '!=', 'web')], context=request.context)
installed = set(x['name'] for x in m.read(cr, 1, ids, ['name'], context=request.context))
mods = ['', "web"] + sorted(installed)
mods = [''] + openerp.conf.server_wide_modules + sorted(installed)
self._routing_map = http.routing_map(mods, False, converters=self._get_converters())
return self._routing_map

View File

@ -411,6 +411,7 @@ class ir_mail_server(osv.osv):
email_to = message['To']
email_cc = message['Cc']
email_bcc = message['Bcc']
smtp_to_list = filter(None, tools.flatten(map(extract_rfc2822_addresses,[email_to, email_cc, email_bcc])))
assert smtp_to_list, "At least one valid recipient address should be specified for outgoing emails (To/Cc/Bcc)"

View File

@ -3,7 +3,7 @@
##############################################################################
#
# OpenERP, Open Source Business Applications
# Copyright (C) 2004-2012 OpenERP S.A. (<http://openerp.com>).
# Copyright (C) 2004-2014 OpenERP S.A. (<http://openerp.com>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
@ -29,7 +29,7 @@ import openerp.modules.registry
from openerp import SUPERUSER_ID
from openerp import tools
from openerp.osv import fields,osv
from openerp.osv.orm import Model
from openerp.osv.orm import Model, browse_null
from openerp.tools.safe_eval import safe_eval as eval
from openerp.tools import config
from openerp.tools.translate import _
@ -737,7 +737,7 @@ class ir_model_access(osv.osv):
msg_params = (model_name,)
_logger.warning('Access Denied by ACLs for operation: %s, uid: %s, model: %s', mode, uid, model_name)
msg = '%s %s' % (msg_heads[mode], msg_tail)
raise except_orm(_('Access Denied'), msg % msg_params)
raise openerp.exceptions.AccessError(msg % msg_params)
return r or False
__cache_clearing_methods = []
@ -853,24 +853,58 @@ class ir_model_data(osv.osv):
if not cr.fetchone():
cr.execute('CREATE INDEX ir_model_data_module_name_index ON ir_model_data (module, name)')
@tools.ormcache()
# NEW V8 API
@tools.ormcache(skiparg=3)
def xmlid_lookup(self, cr, uid, xmlid):
"""Low level xmlid lookup
Return (id, res_model, res_id) or raise ValueError if not found
"""
module, name = xmlid.split('.', 1)
ids = self.search(cr, uid, [('module','=',module), ('name','=', name)])
if not ids:
raise ValueError('External ID not found in the system: %s' % (xmlid))
# the sql constraints ensure us we have only one result
res = self.read(cr, uid, ids[0], ['model', 'res_id'])
if not res['res_id']:
raise ValueError('External ID not found in the system: %s' % (xmlid))
return ids[0], res['model'], res['res_id']
def xmlid_to_res_model_res_id(self, cr, uid, xmlid, raise_if_not_found=False):
""" Return (res_model, res_id)"""
try:
return self.xmlid_lookup(cr, uid, xmlid)[1:3]
except ValueError:
if raise_if_not_found:
raise
return (False, False)
def xmlid_to_res_id(self, cr, uid, xmlid, raise_if_not_found=False):
""" Returns res_id """
return self.xmlid_to_res_model_res_id(cr, uid, xmlid, raise_if_not_found)[1]
def xmlid_to_object(self, cr, uid, xmlid, raise_if_not_found=False, context=None):
""" Return a browse_record
if not found and raise_if_not_found is True return the browse_null
"""
t = self.xmlid_to_res_model_res_id(cr, uid, xmlid, raise_if_not_found)
res_model, res_id = t
if res_model and res_id:
record = self.pool[res_model].browse(cr, uid, res_id, context=context)
if record.exists():
return record
if raise_if_not_found:
raise ValueError('No record found for unique ID %s. It may have been deleted.' % (xml_id))
return browse_null()
# OLD API
def _get_id(self, cr, uid, module, xml_id):
"""Returns the id of the ir.model.data record corresponding to a given module and xml_id (cached) or raise a ValueError if not found"""
ids = self.search(cr, uid, [('module','=',module), ('name','=', xml_id)])
if not ids:
raise ValueError('No such external ID currently defined in the system: %s.%s' % (module, xml_id))
# the sql constraints ensure us we have only one result
return ids[0]
return self.xmlid_lookup(cr, uid, "%s.%s" % (module, xml_id))[0]
@tools.ormcache()
def get_object_reference(self, cr, uid, module, xml_id):
"""Returns (model, res_id) corresponding to a given module and xml_id (cached) or raise ValueError if not found"""
data_id = self._get_id(cr, uid, module, xml_id)
#assuming data_id is not False, as it was checked upstream
res = self.read(cr, uid, data_id, ['model', 'res_id'])
if not res['res_id']:
raise ValueError('No such external ID currently defined in the system: %s.%s' % (module, xml_id))
return res['model'], res['res_id']
return self.xmlid_lookup(cr, uid, "%s.%s" % (module, xml_id))[1:3]
def check_object_reference(self, cr, uid, module, xml_id, raise_on_access_error=False):
"""Returns (model, res_id) corresponding to a given module and xml_id (cached), if and only if the user has the necessary access rights
@ -885,12 +919,11 @@ class ir_model_data(osv.osv):
return model, False
def get_object(self, cr, uid, module, xml_id, context=None):
"""Returns a browsable record for the given module name and xml_id or raise ValueError if not found"""
res_model, res_id = self.get_object_reference(cr, uid, module, xml_id)
result = self.pool[res_model].browse(cr, uid, res_id, context=context)
if not result.exists():
raise ValueError('No record found for unique ID %s.%s. It may have been deleted.' % (module, xml_id))
return result
""" Returns a browsable record for the given module name and xml_id.
If not found, raise a ValueError or return a browse_null, depending
on the value of `raise_exception`.
"""
return self.xmlid_to_object(cr, uid, "%s.%s" % (module, xml_id), raise_if_not_found=True, context=context)
def _update_dummy(self,cr, uid, model, module, xml_id=False, store=True):
if not xml_id:
@ -907,8 +940,7 @@ class ir_model_data(osv.osv):
:returns: itself
"""
self._get_id.clear_cache(self)
self.get_object_reference.clear_cache(self)
self.xmlid_lookup.clear_cache(self)
return self
def unlink(self, cr, uid, ids, context=None):
@ -929,15 +961,17 @@ class ir_model_data(osv.osv):
return False
action_id = False
if xml_id:
cr.execute('''SELECT imd.id, imd.res_id, md.id, imd.model
cr.execute('''SELECT imd.id, imd.res_id, md.id, imd.model, imd.noupdate
FROM ir_model_data imd LEFT JOIN %s md ON (imd.res_id = md.id)
WHERE imd.module=%%s AND imd.name=%%s''' % model_obj._table,
(module, xml_id))
results = cr.fetchall()
for imd_id2,res_id2,real_id2,real_model in results:
for imd_id2,res_id2,real_id2,real_model,noupdate_imd in results:
# In update mode, do not update a record if it's ir.model.data is flagged as noupdate
if mode == 'update' and noupdate_imd:
return res_id2
if not real_id2:
self._get_id.clear_cache(self, uid, module, xml_id)
self.get_object_reference.clear_cache(self, uid, module, xml_id)
self.clear_caches()
cr.execute('delete from ir_model_data where id=%s', (imd_id2,))
res_id = False
else:

View File

@ -0,0 +1,850 @@
# -*- coding: utf-8 -*-
import collections
import cStringIO
import datetime
import json
import logging
import math
import re
import sys
import xml # FIXME use lxml and etree
import babel
import babel.dates
import werkzeug.utils
from PIL import Image
import openerp.tools
from openerp.tools.safe_eval import safe_eval as eval
from openerp.osv import osv, orm, fields
from openerp.tools.translate import _
_logger = logging.getLogger(__name__)
#--------------------------------------------------------------------
# QWeb template engine
#--------------------------------------------------------------------
class QWebException(Exception):
def __init__(self, message, **kw):
Exception.__init__(self, message)
self.qweb = dict(kw)
class QWebTemplateNotFound(QWebException):
pass
def convert_to_qweb_exception(etype=None, **kw):
if etype is None:
etype = QWebException
orig_type, original, tb = sys.exc_info()
try:
raise etype, original, tb
except etype, e:
for k, v in kw.items():
e.qweb[k] = v
# Will use `raise foo from bar` in python 3 and rename cause to __cause__
e.qweb['cause'] = original
return e
class QWebContext(dict):
def __init__(self, cr, uid, data, loader=None, templates=None, context=None):
self.cr = cr
self.uid = uid
self.loader = loader
self.templates = templates or {}
self.context = context
dic = dict(data)
super(QWebContext, self).__init__(dic)
self['defined'] = lambda key: key in self
def safe_eval(self, expr):
locals_dict = collections.defaultdict(lambda: None)
locals_dict.update(self)
locals_dict.pop('cr', None)
locals_dict.pop('loader', None)
return eval(expr, None, locals_dict, nocopy=True, locals_builtins=True)
def copy(self):
return QWebContext(self.cr, self.uid, dict.copy(self),
loader=self.loader,
templates=self.templates,
context=self.context)
def __copy__(self):
return self.copy()
class QWeb(orm.AbstractModel):
"""QWeb Xml templating engine
The templating engine use a very simple syntax based "magic" xml
attributes, to produce textual output (even non-xml).
The core magic attributes are:
flow attributes:
t-if t-foreach t-call
output attributes:
t-att t-raw t-esc t-trim
assignation attribute:
t-set
QWeb can be extended like any OpenERP model and new attributes can be
added.
If you need to customize t-fields rendering, subclass the ir.qweb.field
model (and its sub-models) then override :meth:`~.get_converter_for` to
fetch the right field converters for your qweb model.
Beware that if you need extensions or alterations which could be
incompatible with other subsystems, you should create a local object
inheriting from ``ir.qweb`` and customize that.
"""
_name = 'ir.qweb'
node = xml.dom.Node
_void_elements = frozenset([
'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen',
'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr'])
_format_regex = re.compile(
'(?:'
# ruby-style pattern
'#\{(.+?)\}'
')|(?:'
# jinja-style pattern
'\{\{(.+?)\}\}'
')')
def __init__(self, pool, cr):
super(QWeb, self).__init__(pool, cr)
self._render_tag = self.prefixed_methods('render_tag_')
self._render_att = self.prefixed_methods('render_att_')
def prefixed_methods(self, prefix):
""" Extracts all methods prefixed by ``prefix``, and returns a mapping
of (t-name, method) where the t-name is the method name with prefix
removed and underscore converted to dashes
:param str prefix:
:return: dict
"""
n_prefix = len(prefix)
return dict(
(name[n_prefix:].replace('_', '-'), getattr(type(self), name))
for name in dir(self)
if name.startswith(prefix)
)
def register_tag(self, tag, func):
self._render_tag[tag] = func
def add_template(self, qwebcontext, name, node):
"""Add a parsed template in the context. Used to preprocess templates."""
qwebcontext.templates[name] = node
def load_document(self, document, qwebcontext):
"""
Loads an XML document and installs any contained template in the engine
"""
if hasattr(document, 'documentElement'):
dom = document
elif document.startswith("<?xml"):
dom = xml.dom.minidom.parseString(document)
else:
dom = xml.dom.minidom.parse(document)
for node in dom.documentElement.childNodes:
if node.nodeType == self.node.ELEMENT_NODE and node.getAttribute('t-name'):
name = str(node.getAttribute("t-name"))
self.add_template(qwebcontext, name, node)
def get_template(self, name, qwebcontext):
origin_template = qwebcontext.get('__caller__') or qwebcontext['__stack__'][0]
if qwebcontext.loader and name not in qwebcontext.templates:
try:
xml_doc = qwebcontext.loader(name)
except ValueError:
raise convert_to_qweb_exception(QWebTemplateNotFound, message="Loader could not find template %r" % name, template=origin_template)
self.load_document(xml_doc, qwebcontext=qwebcontext)
if name in qwebcontext.templates:
return qwebcontext.templates[name]
raise QWebTemplateNotFound("Template %r not found" % name, template=origin_template)
def eval(self, expr, qwebcontext):
try:
return qwebcontext.safe_eval(expr)
except Exception:
template = qwebcontext.get('__template__')
raise convert_to_qweb_exception(message="Could not evaluate expression %r" % expr, expression=expr, template=template)
def eval_object(self, expr, qwebcontext):
return self.eval(expr, qwebcontext)
def eval_str(self, expr, qwebcontext):
if expr == "0":
return qwebcontext.get(0, '')
val = self.eval(expr, qwebcontext)
if isinstance(val, unicode):
return val.encode("utf8")
if val is False or val is None:
return ''
return str(val)
def eval_format(self, expr, qwebcontext):
expr, replacements = self._format_regex.subn(
lambda m: self.eval_str(m.group(1) or m.group(2), qwebcontext),
expr
)
if replacements:
return expr
try:
return str(expr % qwebcontext)
except Exception:
template = qwebcontext.get('__template__')
raise convert_to_qweb_exception(message="Format error for expression %r" % expr, expression=expr, template=template)
def eval_bool(self, expr, qwebcontext):
return int(bool(self.eval(expr, qwebcontext)))
def render(self, cr, uid, id_or_xml_id, qwebcontext=None, loader=None, context=None):
if qwebcontext is None:
qwebcontext = {}
if not isinstance(qwebcontext, QWebContext):
qwebcontext = QWebContext(cr, uid, qwebcontext, loader=loader, context=context)
qwebcontext['__template__'] = id_or_xml_id
stack = qwebcontext.get('__stack__', [])
if stack:
qwebcontext['__caller__'] = stack[-1]
stack.append(id_or_xml_id)
qwebcontext['__stack__'] = stack
qwebcontext['xmlid'] = str(stack[0]) # Temporary fix
return self.render_node(self.get_template(id_or_xml_id, qwebcontext), qwebcontext)
def render_node(self, element, qwebcontext):
result = ""
if element.nodeType == self.node.TEXT_NODE or element.nodeType == self.node.CDATA_SECTION_NODE:
result = element.data.encode("utf8")
elif element.nodeType == self.node.ELEMENT_NODE:
generated_attributes = ""
t_render = None
template_attributes = {}
for (attribute_name, attribute_value) in element.attributes.items():
attribute_name = str(attribute_name)
if attribute_name == "groups":
cr = qwebcontext.get('request') and qwebcontext['request'].cr or None
uid = qwebcontext.get('request') and qwebcontext['request'].uid or None
can_see = self.user_has_groups(cr, uid, groups=attribute_value)
if not can_see:
return ''
continue
if isinstance(attribute_value, unicode):
attribute_value = attribute_value.encode("utf8")
else:
attribute_value = attribute_value.nodeValue.encode("utf8")
if attribute_name.startswith("t-"):
for attribute in self._render_att:
if attribute_name[2:].startswith(attribute):
att, val = self._render_att[attribute](self, element, attribute_name, attribute_value, qwebcontext)
generated_attributes += val and ' %s="%s"' % (att, werkzeug.utils.escape(val)) or " "
break
else:
if attribute_name[2:] in self._render_tag:
t_render = attribute_name[2:]
template_attributes[attribute_name[2:]] = attribute_value
else:
generated_attributes += ' %s="%s"' % (attribute_name, werkzeug.utils.escape(attribute_value))
if 'debug' in template_attributes:
debugger = template_attributes.get('debug', 'pdb')
__import__(debugger).set_trace() # pdb, ipdb, pudb, ...
if t_render:
result = self._render_tag[t_render](self, element, template_attributes, generated_attributes, qwebcontext)
else:
result = self.render_element(element, template_attributes, generated_attributes, qwebcontext)
if isinstance(result, unicode):
return result.encode('utf-8')
return result
def render_element(self, element, template_attributes, generated_attributes, qwebcontext, inner=None):
# element: element
# template_attributes: t-* attributes
# generated_attributes: generated attributes
# qwebcontext: values
# inner: optional innerXml
if inner:
g_inner = inner
else:
g_inner = []
for current_node in element.childNodes:
try:
g_inner.append(self.render_node(current_node, qwebcontext))
except QWebException:
raise
except Exception:
template = qwebcontext.get('__template__')
raise convert_to_qweb_exception(message="Could not render element %r" % element.nodeName, node=element, template=template)
name = str(element.nodeName)
inner = "".join(g_inner)
trim = template_attributes.get("trim", 0)
if trim == 0:
pass
elif trim == 'left':
inner = inner.lstrip()
elif trim == 'right':
inner = inner.rstrip()
elif trim == 'both':
inner = inner.strip()
if name == "t":
return inner
elif len(inner) or name not in self._void_elements:
return "<%s%s>%s</%s>" % tuple(
qwebcontext if isinstance(qwebcontext, str) else qwebcontext.encode('utf-8')
for qwebcontext in (name, generated_attributes, inner, name)
)
else:
return "<%s%s/>" % (name, generated_attributes)
# Attributes
def render_att_att(self, element, attribute_name, attribute_value, qwebcontext):
if attribute_name.startswith("t-attf-"):
att, val = attribute_name[7:], self.eval_format(attribute_value, qwebcontext)
elif attribute_name.startswith("t-att-"):
att, val = attribute_name[6:], self.eval(attribute_value, qwebcontext)
if isinstance(val, unicode):
val = val.encode("utf8")
else:
att, val = self.eval_object(attribute_value, qwebcontext)
return att, val
# Tags
def render_tag_raw(self, element, template_attributes, generated_attributes, qwebcontext):
inner = self.eval_str(template_attributes["raw"], qwebcontext)
return self.render_element(element, template_attributes, generated_attributes, qwebcontext, inner)
def render_tag_esc(self, element, template_attributes, generated_attributes, qwebcontext):
inner = werkzeug.utils.escape(self.eval_str(template_attributes["esc"], qwebcontext))
return self.render_element(element, template_attributes, generated_attributes, qwebcontext, inner)
def render_tag_foreach(self, element, template_attributes, generated_attributes, qwebcontext):
expr = template_attributes["foreach"]
enum = self.eval_object(expr, qwebcontext)
if enum is not None:
var = template_attributes.get('as', expr).replace('.', '_')
copy_qwebcontext = qwebcontext.copy()
size = -1
if isinstance(enum, (list, tuple)):
size = len(enum)
elif hasattr(enum, 'count'):
size = enum.count()
copy_qwebcontext["%s_size" % var] = size
copy_qwebcontext["%s_all" % var] = enum
index = 0
ru = []
for i in enum:
copy_qwebcontext["%s_value" % var] = i
copy_qwebcontext["%s_index" % var] = index
copy_qwebcontext["%s_first" % var] = index == 0
copy_qwebcontext["%s_even" % var] = index % 2
copy_qwebcontext["%s_odd" % var] = (index + 1) % 2
copy_qwebcontext["%s_last" % var] = index + 1 == size
if index % 2:
copy_qwebcontext["%s_parity" % var] = 'odd'
else:
copy_qwebcontext["%s_parity" % var] = 'even'
if 'as' in template_attributes:
copy_qwebcontext[var] = i
elif isinstance(i, dict):
copy_qwebcontext.update(i)
ru.append(self.render_element(element, template_attributes, generated_attributes, copy_qwebcontext))
index += 1
return "".join(ru)
else:
template = qwebcontext.get('__template__')
raise QWebException("foreach enumerator %r is not defined while rendering template %r" % (expr, template), template=template)
def render_tag_if(self, element, template_attributes, generated_attributes, qwebcontext):
if self.eval_bool(template_attributes["if"], qwebcontext):
return self.render_element(element, template_attributes, generated_attributes, qwebcontext)
return ""
def render_tag_call(self, element, template_attributes, generated_attributes, qwebcontext):
d = qwebcontext.copy()
d[0] = self.render_element(element, template_attributes, generated_attributes, d)
cr = d.get('request') and d['request'].cr or None
uid = d.get('request') and d['request'].uid or None
return self.render(cr, uid, self.eval_format(template_attributes["call"], d), d)
def render_tag_set(self, element, template_attributes, generated_attributes, qwebcontext):
if "value" in template_attributes:
qwebcontext[template_attributes["set"]] = self.eval_object(template_attributes["value"], qwebcontext)
elif "valuef" in template_attributes:
qwebcontext[template_attributes["set"]] = self.eval_format(template_attributes["valuef"], qwebcontext)
else:
qwebcontext[template_attributes["set"]] = self.render_element(element, template_attributes, generated_attributes, qwebcontext)
return ""
def render_tag_field(self, element, template_attributes, generated_attributes, qwebcontext):
""" eg: <span t-record="browse_record(res.partner, 1)" t-field="phone">+1 555 555 8069</span>"""
node_name = element.nodeName
assert node_name not in ("table", "tbody", "thead", "tfoot", "tr", "td",
"li", "ul", "ol", "dl", "dt", "dd"),\
"RTE widgets do not work correctly on %r elements" % node_name
assert node_name != 't',\
"t-field can not be used on a t element, provide an actual HTML node"
record, field_name = template_attributes["field"].rsplit('.', 1)
record = self.eval_object(record, qwebcontext)
column = record._model._all_columns[field_name].column
options = json.loads(template_attributes.get('field-options') or '{}')
field_type = get_field_type(column, options)
converter = self.get_converter_for(field_type)
return converter.to_html(qwebcontext.cr, qwebcontext.uid, field_name, record, options,
element, template_attributes, generated_attributes, qwebcontext, context=qwebcontext.context)
def get_converter_for(self, field_type):
return self.pool.get('ir.qweb.field.' + field_type,
self.pool['ir.qweb.field'])
#--------------------------------------------------------------------
# QWeb Fields converters
#--------------------------------------------------------------------
class FieldConverter(osv.AbstractModel):
""" Used to convert a t-field specification into an output HTML field.
:meth:`~.to_html` is the entry point of this conversion from QWeb, it:
* converts the record value to html using :meth:`~.record_to_html`
* generates the metadata attributes (``data-oe-``) to set on the root
result node
* generates the root result node itself through :meth:`~.render_element`
"""
_name = 'ir.qweb.field'
def attributes(self, cr, uid, field_name, record, options,
source_element, g_att, t_att, qweb_context,
context=None):
"""
Generates the metadata attributes (prefixed by ``data-oe-`` for the
root node of the field conversion. Attribute values are escaped by the
parent using ``werkzeug.utils.escape``.
The default attributes are:
* ``model``, the name of the record's model
* ``id`` the id of the record to which the field belongs
* ``field`` the name of the converted field
* ``type`` the logical field type (widget, may not match the column's
``type``, may not be any _column subclass name)
* ``translate``, a boolean flag (``0`` or ``1``) denoting whether the
column is translatable
* ``expression``, the original expression
:returns: iterable of (attribute name, attribute value) pairs.
"""
column = record._model._all_columns[field_name].column
field_type = get_field_type(column, options)
return [
('data-oe-model', record._model._name),
('data-oe-id', record.id),
('data-oe-field', field_name),
('data-oe-type', field_type),
('data-oe-expression', t_att['field']),
]
def value_to_html(self, cr, uid, value, column, options=None, context=None):
""" Converts a single value to its HTML version/output
"""
if not value: return ''
return value
def record_to_html(self, cr, uid, field_name, record, column, options=None, context=None):
""" Converts the specified field of the browse_record ``record`` to
HTML
"""
return self.value_to_html(
cr, uid, record[field_name], column, options=options, context=context)
def to_html(self, cr, uid, field_name, record, options,
source_element, t_att, g_att, qweb_context, context=None):
""" Converts a ``t-field`` to its HTML output. A ``t-field`` may be
extended by a ``t-field-options``, which is a JSON-serialized mapping
of configuration values.
A default configuration key is ``widget`` which can override the
field's own ``_type``.
"""
content = None
try:
content = self.record_to_html(
cr, uid, field_name, record,
record._model._all_columns[field_name].column,
options, context=context)
if options.get('html-escape', True):
content = werkzeug.utils.escape(content)
elif hasattr(content, '__html__'):
content = content.__html__()
except Exception:
_logger.warning("Could not get field %s for model %s",
field_name, record._model._name, exc_info=True)
content = None
g_att += ''.join(
' %s="%s"' % (name, werkzeug.utils.escape(value))
for name, value in self.attributes(
cr, uid, field_name, record, options,
source_element, g_att, t_att, qweb_context)
)
return self.render_element(cr, uid, source_element, t_att, g_att,
qweb_context, content)
def qweb_object(self):
return self.pool['ir.qweb']
def render_element(self, cr, uid, source_element, t_att, g_att,
qweb_context, content):
""" Final rendering hook, by default just calls ir.qweb's ``render_element``
"""
return self.qweb_object().render_element(
source_element, t_att, g_att, qweb_context, content or '')
def user_lang(self, cr, uid, context):
"""
Fetches the res.lang object corresponding to the language code stored
in the user's context. Fallbacks to en_US if no lang is present in the
context *or the language code is not valid*.
:returns: res.lang browse_record
"""
if context is None: context = {}
lang_code = context.get('lang') or 'en_US'
Lang = self.pool['res.lang']
lang_ids = Lang.search(cr, uid, [('code', '=', lang_code)], context=context) \
or Lang.search(cr, uid, [('code', '=', 'en_US')], context=context)
return Lang.browse(cr, uid, lang_ids[0], context=context)
class FloatConverter(osv.AbstractModel):
_name = 'ir.qweb.field.float'
_inherit = 'ir.qweb.field'
def precision(self, cr, uid, column, options=None, context=None):
_, precision = column.digits or (None, None)
return precision
def value_to_html(self, cr, uid, value, column, options=None, context=None):
if context is None:
context = {}
precision = self.precision(cr, uid, column, options=options, context=context)
fmt = '%f' if precision is None else '%.{precision}f'
lang_code = context.get('lang') or 'en_US'
lang = self.pool['res.lang']
formatted = lang.format(cr, uid, [lang_code], fmt.format(precision=precision), value, grouping=True)
# %f does not strip trailing zeroes. %g does but its precision causes
# it to switch to scientific notation starting at a million *and* to
# strip decimals. So use %f and if no precision was specified manually
# strip trailing 0.
if not precision:
formatted = re.sub(r'(?:(0|\d+?)0+)$', r'\1', formatted)
return formatted
class DateConverter(osv.AbstractModel):
_name = 'ir.qweb.field.date'
_inherit = 'ir.qweb.field'
def value_to_html(self, cr, uid, value, column, options=None, context=None):
if not value: return ''
lang = self.user_lang(cr, uid, context=context)
locale = babel.Locale.parse(lang.code)
if isinstance(value, basestring):
value = datetime.datetime.strptime(
value, openerp.tools.DEFAULT_SERVER_DATE_FORMAT)
if options and 'format' in options:
pattern = options['format']
else:
strftime_pattern = lang.date_format
pattern = openerp.tools.posix_to_ldml(strftime_pattern, locale=locale)
return babel.dates.format_datetime(
value, format=pattern,
locale=locale)
class DateTimeConverter(osv.AbstractModel):
_name = 'ir.qweb.field.datetime'
_inherit = 'ir.qweb.field'
def value_to_html(self, cr, uid, value, column, options=None, context=None):
if not value: return ''
lang = self.user_lang(cr, uid, context=context)
locale = babel.Locale.parse(lang.code)
if isinstance(value, basestring):
value = datetime.datetime.strptime(
value, openerp.tools.DEFAULT_SERVER_DATETIME_FORMAT)
value = column.context_timestamp(
cr, uid, timestamp=value, context=context)
if options and 'format' in options:
pattern = options['format']
else:
strftime_pattern = (u"%s %s" % (lang.date_format, lang.time_format))
pattern = openerp.tools.posix_to_ldml(strftime_pattern, locale=locale)
return babel.dates.format_datetime(value, format=pattern, locale=locale)
class TextConverter(osv.AbstractModel):
_name = 'ir.qweb.field.text'
_inherit = 'ir.qweb.field'
def value_to_html(self, cr, uid, value, column, options=None, context=None):
"""
Escapes the value and converts newlines to br. This is bullshit.
"""
if not value: return ''
return nl2br(value, options=options)
class SelectionConverter(osv.AbstractModel):
_name = 'ir.qweb.field.selection'
_inherit = 'ir.qweb.field'
def record_to_html(self, cr, uid, field_name, record, column, options=None, context=None):
value = record[field_name]
if not value: return ''
selection = dict(fields.selection.reify(
cr, uid, record._model, column))
return self.value_to_html(
cr, uid, selection[value], column, options=options)
class ManyToOneConverter(osv.AbstractModel):
_name = 'ir.qweb.field.many2one'
_inherit = 'ir.qweb.field'
def record_to_html(self, cr, uid, field_name, record, column, options=None, context=None):
[read] = record.read([field_name])
if not read[field_name]: return ''
_, value = read[field_name]
return nl2br(value, options=options)
class HTMLConverter(osv.AbstractModel):
_name = 'ir.qweb.field.html'
_inherit = 'ir.qweb.field'
def value_to_html(self, cr, uid, value, column, options=None, context=None):
return HTMLSafe(value or '')
class ImageConverter(osv.AbstractModel):
""" ``image`` widget rendering, inserts a data:uri-using image tag in the
document. May be overridden by e.g. the website module to generate links
instead.
.. todo:: what happens if different output need different converters? e.g.
reports may need embedded images or FS links whereas website
needs website-aware
"""
_name = 'ir.qweb.field.image'
_inherit = 'ir.qweb.field'
def value_to_html(self, cr, uid, value, column, options=None, context=None):
try:
image = Image.open(cStringIO.StringIO(value.decode('base64')))
image.verify()
except IOError:
raise ValueError("Non-image binary fields can not be converted to HTML")
except: # image.verify() throws "suitable exceptions", I have no idea what they are
raise ValueError("Invalid image content")
return HTMLSafe('<img src="data:%s;base64,%s">' % (Image.MIME[image.format], value))
class MonetaryConverter(osv.AbstractModel):
""" ``monetary`` converter, has a mandatory option
``display_currency``.
The currency is used for formatting *and rounding* of the float value. It
is assumed that the linked res_currency has a non-empty rounding value and
res.currency's ``round`` method is used to perform rounding.
.. note:: the monetary converter internally adds the qweb context to its
options mapping, so that the context is available to callees.
It's set under the ``_qweb_context`` key.
"""
_name = 'ir.qweb.field.monetary'
_inherit = 'ir.qweb.field'
def to_html(self, cr, uid, field_name, record, options,
source_element, t_att, g_att, qweb_context, context=None):
options['_qweb_context'] = qweb_context
return super(MonetaryConverter, self).to_html(
cr, uid, field_name, record, options,
source_element, t_att, g_att, qweb_context, context=context)
def record_to_html(self, cr, uid, field_name, record, column, options, context=None):
if context is None:
context = {}
Currency = self.pool['res.currency']
display = self.display_currency(cr, uid, options)
# lang.format mandates a sprintf-style format. These formats are non-
# minimal (they have a default fixed precision instead), and
# lang.format will not set one by default. currency.round will not
# provide one either. So we need to generate a precision value
# (integer > 0) from the currency's rounding (a float generally < 1.0).
#
# The log10 of the rounding should be the number of digits involved if
# negative, if positive clamp to 0 digits and call it a day.
# nb: int() ~ floor(), we want nearest rounding instead
precision = int(round(math.log10(display.rounding)))
fmt = "%.{0}f".format(-precision if precision < 0 else 0)
lang_code = context.get('lang') or 'en_US'
lang = self.pool['res.lang']
formatted_amount = lang.format(cr, uid, [lang_code],
fmt, Currency.round(cr, uid, display, record[field_name]),
grouping=True, monetary=True)
pre = post = u''
if display.position == 'before':
pre = u'{symbol} '
else:
post = u' {symbol}'
return HTMLSafe(u'{pre}<span class="oe_currency_value">{0}</span>{post}'.format(
formatted_amount,
pre=pre, post=post,
).format(
symbol=display.symbol,
))
def display_currency(self, cr, uid, options):
return self.qweb_object().eval_object(
options['display_currency'], options['_qweb_context'])
TIMEDELTA_UNITS = (
('year', 3600 * 24 * 365),
('month', 3600 * 24 * 30),
('week', 3600 * 24 * 7),
('day', 3600 * 24),
('hour', 3600),
('minute', 60),
('second', 1)
)
class DurationConverter(osv.AbstractModel):
""" ``duration`` converter, to display integral or fractional values as
human-readable time spans (e.g. 1.5 as "1 hour 30 minutes").
Can be used on any numerical field.
Has a mandatory option ``unit`` which can be one of ``second``, ``minute``,
``hour``, ``day``, ``week`` or ``year``, used to interpret the numerical
field value before converting it.
Sub-second values will be ignored.
"""
_name = 'ir.qweb.field.duration'
_inherit = 'ir.qweb.field'
def value_to_html(self, cr, uid, value, column, options=None, context=None):
units = dict(TIMEDELTA_UNITS)
if value < 0:
raise ValueError(_("Durations can't be negative"))
if not options or options.get('unit') not in units:
raise ValueError(_("A unit must be provided to duration widgets"))
locale = babel.Locale.parse(
self.user_lang(cr, uid, context=context).code)
factor = units[options['unit']]
sections = []
r = value * factor
for unit, secs_per_unit in TIMEDELTA_UNITS:
v, r = divmod(r, secs_per_unit)
if not v: continue
section = babel.dates.format_timedelta(
v*secs_per_unit, threshold=1, locale=locale)
if section:
sections.append(section)
return u' '.join(sections)
class RelativeDatetimeConverter(osv.AbstractModel):
_name = 'ir.qweb.field.relative'
_inherit = 'ir.qweb.field'
def value_to_html(self, cr, uid, value, column, options=None, context=None):
parse_format = openerp.tools.DEFAULT_SERVER_DATETIME_FORMAT
locale = babel.Locale.parse(
self.user_lang(cr, uid, context=context).code)
if isinstance(value, basestring):
value = datetime.datetime.strptime(value, parse_format)
# value should be a naive datetime in UTC. So is fields.datetime.now()
reference = datetime.datetime.strptime(column.now(), parse_format)
return babel.dates.format_timedelta(
value - reference, add_direction=True, locale=locale)
class HTMLSafe(object):
""" HTMLSafe string wrapper, Werkzeug's escape() has special handling for
objects with a ``__html__`` methods but AFAIK does not provide any such
object.
Wrapping a string in HTML will prevent its escaping
"""
__slots__ = ['string']
def __init__(self, string):
self.string = string
def __html__(self):
return self.string
def __str__(self):
s = self.string
if isinstance(s, unicode):
return s.encode('utf-8')
return s
def __unicode__(self):
s = self.string
if isinstance(s, str):
return s.decode('utf-8')
return s
def nl2br(string, options=None):
""" Converts newlines to HTML linebreaks in ``string``. Automatically
escapes content unless options['html-escape'] is set to False, and returns
the result wrapped in an HTMLSafe object.
:param str string:
:param dict options:
:rtype: HTMLSafe
"""
if options is None: options = {}
if options.get('html-escape', True):
string = werkzeug.utils.escape(string)
return HTMLSafe(string.replace('\n', '<br>\n'))
def get_field_type(column, options):
""" Gets a t-field's effective type from the field's column and its options
"""
return options.get('widget', column._type)
# vim:et:

View File

@ -268,13 +268,8 @@ class ir_translation(osv.osv):
return translations
def _set_ids(self, cr, uid, name, tt, lang, ids, value, src=None):
# clear the caches
tr = self._get_ids(cr, uid, name, tt, lang, ids)
for res_id in tr:
if tr[res_id]:
self._get_source.clear_cache(self, uid, name, tt, lang, tr[res_id])
self._get_ids.clear_cache(self, uid, name, tt, lang, res_id)
self._get_source.clear_cache(self, uid, name, tt, lang)
self._get_ids.clear_cache(self)
self._get_source.clear_cache(self)
cr.execute('delete from ir_translation '
'where lang=%s '
@ -294,7 +289,7 @@ class ir_translation(osv.osv):
return len(ids)
@tools.ormcache(skiparg=3)
def _get_source(self, cr, uid, name, types, lang, source=None):
def _get_source(self, cr, uid, name, types, lang, source=None, res_id=None):
"""
Returns the translation for the given combination of name, type, language
and source. All values passed to this method should be unicode (not byte strings),
@ -304,6 +299,7 @@ class ir_translation(osv.osv):
:param types: single string defining type of term to translate (see ``type`` field on ir.translation), or sequence of allowed types (strings)
:param lang: language code of the desired translation
:param source: optional source term to translate (should be unicode)
:param res_id: optional resource id to translate (if used, ``source`` should be set)
:rtype: unicode
:return: the request translation, or an empty unicode string if no translation was
found and `source` was not passed
@ -321,6 +317,9 @@ class ir_translation(osv.osv):
AND type in %s
AND src=%s"""
params = (lang or '', types, tools.ustr(source))
if res_id:
query += "AND res_id=%s"
params += (res_id,)
if name:
query += " AND name=%s"
params += (tools.ustr(name),)
@ -342,8 +341,9 @@ class ir_translation(osv.osv):
if context is None:
context = {}
ids = super(ir_translation, self).create(cr, uid, vals, context=context)
self._get_source.clear_cache(self, uid, vals.get('name',0), vals.get('type',0), vals.get('lang',0), vals.get('src',0))
self._get_ids.clear_cache(self, uid, vals.get('name',0), vals.get('type',0), vals.get('lang',0), vals.get('res_id',0))
self._get_source.clear_cache(self)
self._get_ids.clear_cache(self)
self.pool['ir.ui.view'].clear_cache()
return ids
def write(self, cursor, user, ids, vals, context=None):
@ -356,9 +356,9 @@ class ir_translation(osv.osv):
if vals.get('value'):
vals.update({'state':'translated'})
result = super(ir_translation, self).write(cursor, user, ids, vals, context=context)
for trans_obj in self.read(cursor, user, ids, ['name','type','res_id','src','lang'], context=context):
self._get_source.clear_cache(self, user, trans_obj['name'], trans_obj['type'], trans_obj['lang'], trans_obj['src'])
self._get_ids.clear_cache(self, user, trans_obj['name'], trans_obj['type'], trans_obj['lang'], trans_obj['res_id'])
self._get_source.clear_cache(self)
self._get_ids.clear_cache(self)
self.pool['ir.ui.view'].clear_cache()
return result
def unlink(self, cursor, user, ids, context=None):
@ -366,9 +366,9 @@ class ir_translation(osv.osv):
context = {}
if isinstance(ids, (int, long)):
ids = [ids]
for trans_obj in self.read(cursor, user, ids, ['name','type','res_id','src','lang'], context=context):
self._get_source.clear_cache(self, user, trans_obj['name'], trans_obj['type'], trans_obj['lang'], trans_obj['src'])
self._get_ids.clear_cache(self, user, trans_obj['name'], trans_obj['type'], trans_obj['lang'], trans_obj['res_id'])
self._get_source.clear_cache(self)
self._get_ids.clear_cache(self)
result = super(ir_translation, self).unlink(cursor, user, ids, context=context)
return result

View File

@ -14,7 +14,7 @@
domain="[('comments', 'like', 'openerp-web')]"/>
<field name="name" operator="="/>
<field name="lang"/>
<field name="source"/>
<field name="src"/>
<field name="value"/>
</search>
</field>

View File

@ -18,20 +18,43 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import collections
import copy
import fnmatch
import logging
from lxml import etree
from operator import itemgetter
import os
import simplejson
import werkzeug
import HTMLParser
import openerp
from openerp import tools
from openerp.osv import fields,osv
from openerp.tools import graph
from openerp.http import request
from openerp.osv import fields, osv, orm
from openerp.tools import graph, SKIPPED_ELEMENT_TYPES
from openerp.tools.safe_eval import safe_eval as eval
from openerp.tools.view_validation import valid_view
from openerp.tools import misc
from openerp.tools.translate import _
_logger = logging.getLogger(__name__)
MOVABLE_BRANDING = ['data-oe-model', 'data-oe-id', 'data-oe-field', 'data-oe-xpath']
def keep_query(*args, **kw):
if not args and not kw:
args = ('*',)
params = kw.copy()
query_params = frozenset(werkzeug.url_decode(request.httprequest.query_string).keys())
for keep_param in args:
for param in fnmatch.filter(query_params, keep_param):
if param not in params and param in request.params:
params[param] = request.params[param]
return werkzeug.urls.url_encode(params)
class view_custom(osv.osv):
_name = 'ir.ui.view.custom'
_order = 'create_date desc' # search(limit=1) should return the last customization
@ -50,59 +73,45 @@ class view_custom(osv.osv):
class view(osv.osv):
_name = 'ir.ui.view'
def _type_field(self, cr, uid, ids, name, args, context=None):
result = {}
for record in self.browse(cr, uid, ids, context):
# Get the type from the inherited view if any.
if record.inherit_id:
result[record.id] = record.inherit_id.type
else:
result[record.id] = etree.fromstring(record.arch.encode('utf8')).tag
def _get_model_data(self, cr, uid, ids, *args, **kwargs):
ir_model_data = self.pool.get('ir.model.data')
data_ids = ir_model_data.search(cr, uid, [('model', '=', self._name), ('res_id', 'in', ids)])
result = dict(zip(ids, data_ids))
return result
_columns = {
'name': fields.char('View Name', required=True),
'model': fields.char('Object', size=64, required=True, select=True),
'model': fields.char('Object', select=True),
'priority': fields.integer('Sequence', required=True),
'type': fields.function(_type_field, type='selection', selection=[
'type': fields.selection([
('tree','Tree'),
('form','Form'),
('mdx','mdx'),
('graph', 'Graph'),
('calendar', 'Calendar'),
('diagram','Diagram'),
('gantt', 'Gantt'),
('kanban', 'Kanban'),
('search','Search')], string='View Type', required=True, select=True, store=True),
('search','Search'),
('qweb', 'QWeb')], string='View Type'),
'arch': fields.text('View Architecture', required=True),
'inherit_id': fields.many2one('ir.ui.view', 'Inherited View', ondelete='cascade', select=True),
'field_parent': fields.char('Child Field',size=64),
'inherit_children_ids': fields.one2many('ir.ui.view','inherit_id', 'Inherit Views'),
'field_parent': fields.char('Child Field'),
'model_data_id': fields.function(_get_model_data, type='many2one', relation='ir.model.data', string="Model Data", store=True),
'xml_id': fields.function(osv.osv.get_xml_id, type='char', size=128, string="External ID",
help="ID of the view defined in xml file"),
'groups_id': fields.many2many('res.groups', 'ir_ui_view_group_rel', 'view_id', 'group_id',
string='Groups', help="If this field is empty, the view applies to all users. Otherwise, the view applies to the users of those groups only."),
'model_ids': fields.one2many('ir.model.data', 'res_id', domain=[('model','=','ir.ui.view')], auto_join=True),
}
_defaults = {
'arch': '<?xml version="1.0"?>\n<tree string="My view">\n\t<field name="name"/>\n</tree>',
'priority': 16,
'type': 'tree',
}
_order = "priority,name"
# Holds the RNG schema
_relaxng_validator = None
def create(self, cr, uid, values, context=None):
if 'type' in values:
_logger.warning("Setting the `type` field is deprecated in the `ir.ui.view` model.")
if not values.get('name'):
if values.get('inherit_id'):
inferred_type = self.browse(cr, uid, values['inherit_id'], context).type
else:
inferred_type = etree.fromstring(values['arch'].encode('utf8')).tag
values['name'] = "%s %s" % (values['model'], inferred_type)
return super(view, self).create(cr, uid, values, context)
def _relaxng(self):
if not self._relaxng_validator:
frng = tools.file_open(os.path.join('base','rng','view.rng'))
@ -115,59 +124,37 @@ class view(osv.osv):
frng.close()
return self._relaxng_validator
def _check_render_view(self, cr, uid, view, context=None):
"""Verify that the given view's hierarchy is valid for rendering, along with all the changes applied by
its inherited views, by rendering it using ``fields_view_get()``.
@param browse_record view: view to validate
@return: the rendered definition (arch) of the view, always utf-8 bytestring (legacy convention)
if no error occurred, else False.
"""
if view.model not in self.pool:
return False
try:
fvg = self.pool[view.model].fields_view_get(cr, uid, view_id=view.id, view_type=view.type, context=context)
return fvg['arch']
except Exception:
_logger.exception('cannot render view %s', view.xml_id)
return False
def _check_xml(self, cr, uid, ids, context=None):
if context is None:
context = {}
context['check_view_ids'] = ids
context = dict(context, check_view_ids=ids)
# Sanity checks: the view should not break anything upon rendering!
# Any exception raised below will cause a transaction rollback.
for view in self.browse(cr, uid, ids, context):
# Sanity check: the view should not break anything upon rendering!
view_arch_utf8 = self._check_render_view(cr, uid, view, context=context)
# always utf-8 bytestring - legacy convention
if not view_arch_utf8: return False
# RNG-based validation is not possible anymore with 7.0 forms
# TODO 7.0: provide alternative assertion-based validation of view_arch_utf8
view_docs = [etree.fromstring(view_arch_utf8)]
if view_docs[0].tag == 'data':
# A <data> element is a wrapper for multiple root nodes
view_docs = view_docs[0]
validator = self._relaxng()
for view_arch in view_docs:
if (view_arch.get('version') < '7.0') and validator and not validator.validate(view_arch):
for error in validator.error_log:
_logger.error(tools.ustr(error))
return False
if not valid_view(view_arch):
return False
return True
def _check_model(self, cr, uid, ids, context=None):
for view in self.browse(cr, uid, ids, context):
if view.model not in self.pool:
return False
view_def = self.read_combined(cr, uid, view.id, None, context=context)
view_arch_utf8 = view_def['arch']
if view.type != 'qweb':
view_doc = etree.fromstring(view_arch_utf8)
# verify that all fields used are valid, etc.
self.postprocess_and_fields(cr, uid, view.model, view_doc, view.id, context=context)
# RNG-based validation is not possible anymore with 7.0 forms
view_docs = [view_doc]
if view_docs[0].tag == 'data':
# A <data> element is a wrapper for multiple root nodes
view_docs = view_docs[0]
validator = self._relaxng()
for view_arch in view_docs:
if (view_arch.get('version') < '7.0') and validator and not validator.validate(view_arch):
for error in validator.error_log:
_logger.error(tools.ustr(error))
return False
if not valid_view(view_arch):
return False
return True
_constraints = [
(_check_model, 'The model name does not exist.', ['model']),
(_check_xml, 'The model name does not exist or the view architecture cannot be rendered.', ['arch', 'model']),
(_check_xml, 'Invalid view definition', ['arch'])
]
def _auto_init(self, cr, context=None):
@ -176,6 +163,73 @@ class view(osv.osv):
if not cr.fetchone():
cr.execute('CREATE INDEX ir_ui_view_model_type_inherit_id ON ir_ui_view (model, inherit_id)')
def create(self, cr, uid, values, context=None):
if 'type' not in values:
if values.get('inherit_id'):
values['type'] = self.browse(cr, uid, values['inherit_id'], context).type
else:
values['type'] = etree.fromstring(values['arch']).tag
if not values.get('name'):
values['name'] = "%s %s" % (values['model'], values['type'])
self.read_template.clear_cache(self)
return super(view, self).create(cr, uid, values, context)
def write(self, cr, uid, ids, vals, context=None):
if not isinstance(ids, (list, tuple)):
ids = [ids]
if context is None:
context = {}
# drop the corresponding view customizations (used for dashboards for example), otherwise
# not all users would see the updated views
custom_view_ids = self.pool.get('ir.ui.view.custom').search(cr, uid, [('ref_id', 'in', ids)])
if custom_view_ids:
self.pool.get('ir.ui.view.custom').unlink(cr, uid, custom_view_ids)
self.read_template.clear_cache(self)
ret = super(view, self).write(cr, uid, ids, vals, context)
# if arch is modified views become noupdatable
if 'arch' in vals and not context.get('install_mode', False):
# TODO: should be doable in a read and a write
for view_ in self.browse(cr, uid, ids, context=context):
if view_.model_data_id:
self.pool.get('ir.model.data').write(cr, openerp.SUPERUSER_ID, view_.model_data_id.id, {'noupdate': True})
return ret
def copy(self, cr, uid, id, default=None, context=None):
if not default:
default = {}
default.update({
'model_ids': [],
})
return super(view, self).copy(cr, uid, id, default, context=context)
# default view selection
def default_view(self, cr, uid, model, view_type, context=None):
""" Fetches the default view for the provided (model, view_type) pair:
view with no parent (inherit_id=Fase) with the lowest priority.
:param str model:
:param int view_type:
:return: id of the default view of False if none found
:rtype: int
"""
domain = [
['model', '=', model],
['type', '=', view_type],
['inherit_id', '=', False],
]
ids = self.search(cr, uid, domain, limit=1, order='priority', context=context)
if not ids:
return False
return ids[0]
#------------------------------------------------------
# Inheritance mecanism
#------------------------------------------------------
def get_inheriting_views_arch(self, cr, uid, view_id, model, context=None):
"""Retrieves the architecture of views that inherit from the given view, from the sets of
views that should currently be used in the system. During the module upgrade phase it
@ -185,43 +239,605 @@ class view(osv.osv):
after the module initialization phase is completely finished.
:param int view_id: id of the view whose inheriting views should be retrieved
:param str model: model identifier of the view's related model (for double-checking)
:param str model: model identifier of the inheriting views.
:rtype: list of tuples
:return: [(view_arch,view_id), ...]
"""
user_groups = frozenset(self.pool.get('res.users').browse(cr, 1, uid, context).groups_id)
check_view_ids = context and context.get('check_view_ids') or (0,)
conditions = [['inherit_id', '=', view_id], ['model', '=', model]]
if self.pool._init:
# Module init currently in progress, only consider views from modules whose code was already loaded
check_view_ids = context and context.get('check_view_ids') or (0,)
query = """SELECT v.id FROM ir_ui_view v LEFT JOIN ir_model_data md ON (md.model = 'ir.ui.view' AND md.res_id = v.id)
WHERE v.inherit_id=%s AND v.model=%s AND (md.module in %s OR v.id in %s)
ORDER BY priority"""
query_params = (view_id, model, tuple(self.pool._init_modules), tuple(check_view_ids))
else:
# Modules fully loaded, consider all views
query = """SELECT v.id FROM ir_ui_view v
WHERE v.inherit_id=%s AND v.model=%s
ORDER BY priority"""
query_params = (view_id, model)
cr.execute(query, query_params)
view_ids = [v[0] for v in cr.fetchall()]
# filter views based on user groups
# Module init currently in progress, only consider views from
# modules whose code is already loaded
conditions.extend([
'|',
['model_ids.module', 'in', tuple(self.pool._init_modules)],
['id', 'in', check_view_ids],
])
view_ids = self.search(cr, uid, conditions, context=context)
return [(view.arch, view.id)
for view in self.browse(cr, 1, view_ids, context)
if not (view.groups_id and user_groups.isdisjoint(view.groups_id))]
def write(self, cr, uid, ids, vals, context=None):
if not isinstance(ids, (list, tuple)):
ids = [ids]
def raise_view_error(self, cr, uid, message, view_id, context=None):
view = self.browse(cr, uid, view_id, context)
not_avail = _('n/a')
message = ("%(msg)s\n\n" +
_("Error context:\nView `%(view_name)s`") +
"\n[view_id: %(viewid)s, xml_id: %(xmlid)s, "
"model: %(model)s, parent_id: %(parent)s]") % \
{
'view_name': view.name or not_avail,
'viewid': view_id or not_avail,
'xmlid': view.xml_id or not_avail,
'model': view.model or not_avail,
'parent': view.inherit_id.id or not_avail,
'msg': message,
}
_logger.error(message)
raise AttributeError(message)
# drop the corresponding view customizations (used for dashboards for example), otherwise
# not all users would see the updated views
custom_view_ids = self.pool.get('ir.ui.view.custom').search(cr, uid, [('ref_id','in',ids)])
if custom_view_ids:
self.pool.get('ir.ui.view.custom').unlink(cr, uid, custom_view_ids)
def locate_node(self, arch, spec):
""" Locate a node in a source (parent) architecture.
return super(view, self).write(cr, uid, ids, vals, context)
Given a complete source (parent) architecture (i.e. the field
`arch` in a view), and a 'spec' node (a node in an inheriting
view that specifies the location in the source view of what
should be changed), return (if it exists) the node in the
source view matching the specification.
:param arch: a parent architecture to modify
:param spec: a modifying node in an inheriting view
:return: a node in the source matching the spec
"""
if spec.tag == 'xpath':
nodes = arch.xpath(spec.get('expr'))
return nodes[0] if nodes else None
elif spec.tag == 'field':
# Only compare the field name: a field can be only once in a given view
# at a given level (and for multilevel expressions, we should use xpath
# inheritance spec anyway).
for node in arch.iter('field'):
if node.get('name') == spec.get('name'):
return node
return None
for node in arch.iter(spec.tag):
if isinstance(node, SKIPPED_ELEMENT_TYPES):
continue
if all(node.get(attr) == spec.get(attr) for attr in spec.attrib
if attr not in ('position','version')):
# Version spec should match parent's root element's version
if spec.get('version') and spec.get('version') != arch.get('version'):
return None
return node
return None
def inherit_branding(self, specs_tree, view_id, source_id):
for node in specs_tree.iterchildren(tag=etree.Element):
xpath = node.getroottree().getpath(node)
if node.tag == 'data' or node.tag == 'xpath':
self.inherit_branding(node, view_id, source_id)
else:
node.set('data-oe-id', str(view_id))
node.set('data-oe-source-id', str(source_id))
node.set('data-oe-xpath', xpath)
node.set('data-oe-model', 'ir.ui.view')
node.set('data-oe-field', 'arch')
return specs_tree
def apply_inheritance_specs(self, cr, uid, source, specs_tree, inherit_id, context=None):
""" Apply an inheriting view (a descendant of the base view)
Apply to a source architecture all the spec nodes (i.e. nodes
describing where and what changes to apply to some parent
architecture) given by an inheriting view.
:param Element source: a parent architecture to modify
:param Elepect specs_tree: a modifying architecture in an inheriting view
:param inherit_id: the database id of specs_arch
:return: a modified source where the specs are applied
:rtype: Element
"""
# Queue of specification nodes (i.e. nodes describing where and
# changes to apply to some parent architecture).
specs = [specs_tree]
while len(specs):
spec = specs.pop(0)
if isinstance(spec, SKIPPED_ELEMENT_TYPES):
continue
if spec.tag == 'data':
specs += [c for c in spec]
continue
node = self.locate_node(source, spec)
if node is not None:
pos = spec.get('position', 'inside')
if pos == 'replace':
if node.getparent() is None:
source = copy.deepcopy(spec[0])
else:
for child in spec:
node.addprevious(child)
node.getparent().remove(node)
elif pos == 'attributes':
for child in spec.getiterator('attribute'):
attribute = (child.get('name'), child.text and child.text.encode('utf8') or None)
if attribute[1]:
node.set(attribute[0], attribute[1])
elif attribute[0] in node.attrib:
del node.attrib[attribute[0]]
else:
sib = node.getnext()
for child in spec:
if pos == 'inside':
node.append(child)
elif pos == 'after':
if sib is None:
node.addnext(child)
node = child
else:
sib.addprevious(child)
elif pos == 'before':
node.addprevious(child)
else:
self.raise_view_error(cr, uid, _("Invalid position attribute: '%s'") % pos, inherit_id, context=context)
else:
attrs = ''.join([
' %s="%s"' % (attr, spec.get(attr))
for attr in spec.attrib
if attr != 'position'
])
tag = "<%s%s>" % (spec.tag, attrs)
self.raise_view_error(cr, uid, _("Element '%s' cannot be located in parent view") % tag, inherit_id, context=context)
return source
def apply_view_inheritance(self, cr, uid, source, source_id, model, context=None):
""" Apply all the (directly and indirectly) inheriting views.
:param source: a parent architecture to modify (with parent modifications already applied)
:param source_id: the database view_id of the parent view
:param model: the original model for which we create a view (not
necessarily the same as the source's model); only the inheriting
views with that specific model will be applied.
:return: a modified source where all the modifying architecture are applied
"""
if context is None: context = {}
sql_inherit = self.pool.get('ir.ui.view').get_inheriting_views_arch(cr, uid, source_id, model, context=context)
for (specs, view_id) in sql_inherit:
specs_tree = etree.fromstring(specs.encode('utf-8'))
if context.get('inherit_branding'):
self.inherit_branding(specs_tree, view_id, source_id)
source = self.apply_inheritance_specs(cr, uid, source, specs_tree, view_id, context=context)
source = self.apply_view_inheritance(cr, uid, source, view_id, model, context=context)
return source
def read_combined(self, cr, uid, view_id, fields=None, context=None):
"""
Utility function to get a view combined with its inherited views.
* Gets the top of the view tree if a sub-view is requested
* Applies all inherited archs on the root view
* Returns the view with all requested fields
.. note:: ``arch`` is always added to the fields list even if not
requested (similar to ``id``)
"""
if context is None: context = {}
# if view_id is not a root view, climb back to the top.
base = v = self.browse(cr, uid, view_id, context=context)
while v.inherit_id:
v = v.inherit_id
root_id = v.id
# arch and model fields are always returned
if fields:
fields = list(set(fields) | set(['arch', 'model']))
# read the view arch
[view] = self.read(cr, uid, [root_id], fields=fields, context=context)
arch_tree = etree.fromstring(view['arch'].encode('utf-8'))
if context.get('inherit_branding'):
arch_tree.attrib.update({
'data-oe-model': 'ir.ui.view',
'data-oe-id': str(root_id),
'data-oe-field': 'arch',
})
# and apply inheritance
arch = self.apply_view_inheritance(
cr, uid, arch_tree, root_id, base.model, context=context)
return dict(view, arch=etree.tostring(arch, encoding='utf-8'))
#------------------------------------------------------
# Postprocessing: translation, groups and modifiers
#------------------------------------------------------
# TODO:
# - split postprocess so that it can be used instead of translate_qweb
# - remove group processing from ir_qweb
#------------------------------------------------------
def postprocess(self, cr, user, model, node, view_id, in_tree_view, model_fields, context=None):
"""Return the description of the fields in the node.
In a normal call to this method, node is a complete view architecture
but it is actually possible to give some sub-node (this is used so
that the method can call itself recursively).
Originally, the field descriptions are drawn from the node itself.
But there is now some code calling fields_get() in order to merge some
of those information in the architecture.
"""
if context is None:
context = {}
result = False
fields = {}
children = True
modifiers = {}
Model = self.pool.get(model)
if not Model:
self.raise_view_error(cr, user, _('Model not found: %(model)s') % dict(model=model),
view_id, context)
def encode(s):
if isinstance(s, unicode):
return s.encode('utf8')
return s
def check_group(node):
"""Apply group restrictions, may be set at view level or model level::
* at view level this means the element should be made invisible to
people who are not members
* at model level (exclusively for fields, obviously), this means
the field should be completely removed from the view, as it is
completely unavailable for non-members
:return: True if field should be included in the result of fields_view_get
"""
if node.tag == 'field' and node.get('name') in Model._all_columns:
column = Model._all_columns[node.get('name')].column
if column.groups and not self.user_has_groups(
cr, user, groups=column.groups, context=context):
node.getparent().remove(node)
fields.pop(node.get('name'), None)
# no point processing view-level ``groups`` anymore, return
return False
if node.get('groups'):
can_see = self.user_has_groups(
cr, user, groups=node.get('groups'), context=context)
if not can_see:
node.set('invisible', '1')
modifiers['invisible'] = True
if 'attrs' in node.attrib:
del(node.attrib['attrs']) #avoid making field visible later
del(node.attrib['groups'])
return True
if node.tag in ('field', 'node', 'arrow'):
if node.get('object'):
attrs = {}
views = {}
xml = "<form>"
for f in node:
if f.tag == 'field':
xml += etree.tostring(f, encoding="utf-8")
xml += "</form>"
new_xml = etree.fromstring(encode(xml))
ctx = context.copy()
ctx['base_model_name'] = model
xarch, xfields = self.postprocess_and_fields(cr, user, node.get('object'), new_xml, view_id, ctx)
views['form'] = {
'arch': xarch,
'fields': xfields
}
attrs = {'views': views}
fields = xfields
if node.get('name'):
attrs = {}
try:
if node.get('name') in Model._columns:
column = Model._columns[node.get('name')]
else:
column = Model._inherit_fields[node.get('name')][2]
except Exception:
column = False
if column:
children = False
views = {}
for f in node:
if f.tag in ('form', 'tree', 'graph', 'kanban', 'calendar'):
node.remove(f)
ctx = context.copy()
ctx['base_model_name'] = model
xarch, xfields = self.postprocess_and_fields(cr, user, column._obj or None, f, view_id, ctx)
views[str(f.tag)] = {
'arch': xarch,
'fields': xfields
}
attrs = {'views': views}
fields[node.get('name')] = attrs
field = model_fields.get(node.get('name'))
if field:
orm.transfer_field_to_modifiers(field, modifiers)
elif node.tag in ('form', 'tree'):
result = Model.view_header_get(cr, user, False, node.tag, context)
if result:
node.set('string', result)
in_tree_view = node.tag == 'tree'
elif node.tag == 'calendar':
for additional_field in ('date_start', 'date_delay', 'date_stop', 'color', 'all_day', 'attendee'):
if node.get(additional_field):
fields[node.get(additional_field)] = {}
if not check_group(node):
# node must be removed, no need to proceed further with its children
return fields
# The view architeture overrides the python model.
# Get the attrs before they are (possibly) deleted by check_group below
orm.transfer_node_to_modifiers(node, modifiers, context, in_tree_view)
# TODO remove attrs counterpart in modifiers when invisible is true ?
# translate view
if 'lang' in context:
Translations = self.pool['ir.translation']
if node.text and node.text.strip():
trans = Translations._get_source(cr, user, model, 'view', context['lang'], node.text.strip())
if trans:
node.text = node.text.replace(node.text.strip(), trans)
if node.tail and node.tail.strip():
trans = Translations._get_source(cr, user, model, 'view', context['lang'], node.tail.strip())
if trans:
node.tail = node.tail.replace(node.tail.strip(), trans)
if node.get('string') and not result:
trans = Translations._get_source(cr, user, model, 'view', context['lang'], node.get('string'))
if trans == node.get('string') and ('base_model_name' in context):
# If translation is same as source, perhaps we'd have more luck with the alternative model name
# (in case we are in a mixed situation, such as an inherited view where parent_view.model != model
trans = Translations._get_source(cr, user, context['base_model_name'], 'view', context['lang'], node.get('string'))
if trans:
node.set('string', trans)
for attr_name in ('confirm', 'sum', 'avg', 'help', 'placeholder'):
attr_value = node.get(attr_name)
if attr_value:
trans = Translations._get_source(cr, user, model, 'view', context['lang'], attr_value)
if trans:
node.set(attr_name, trans)
for f in node:
if children or (node.tag == 'field' and f.tag in ('filter','separator')):
fields.update(self.postprocess(cr, user, model, f, view_id, in_tree_view, model_fields, context))
orm.transfer_modifiers_to_node(modifiers, node)
return fields
def _disable_workflow_buttons(self, cr, user, model, node):
""" Set the buttons in node to readonly if the user can't activate them. """
if model is None or user == 1:
# admin user can always activate workflow buttons
return node
# TODO handle the case of more than one workflow for a model or multiple
# transitions with different groups and same signal
usersobj = self.pool.get('res.users')
buttons = (n for n in node.getiterator('button') if n.get('type') != 'object')
for button in buttons:
user_groups = usersobj.read(cr, user, [user], ['groups_id'])[0]['groups_id']
cr.execute("""SELECT DISTINCT t.group_id
FROM wkf
INNER JOIN wkf_activity a ON a.wkf_id = wkf.id
INNER JOIN wkf_transition t ON (t.act_to = a.id)
WHERE wkf.osv = %s
AND t.signal = %s
AND t.group_id is NOT NULL
""", (model, button.get('name')))
group_ids = [x[0] for x in cr.fetchall() if x[0]]
can_click = not group_ids or bool(set(user_groups).intersection(group_ids))
button.set('readonly', str(int(not can_click)))
return node
def postprocess_and_fields(self, cr, user, model, node, view_id, context=None):
""" Return an architecture and a description of all the fields.
The field description combines the result of fields_get() and
postprocess().
:param node: the architecture as as an etree
:return: a tuple (arch, fields) where arch is the given node as a
string and fields is the description of all the fields.
"""
fields = {}
Model = self.pool.get(model)
if not Model:
self.raise_view_error(cr, user, _('Model not found: %(model)s') % dict(model=model), view_id, context)
if node.tag == 'diagram':
if node.getchildren()[0].tag == 'node':
node_model = self.pool[node.getchildren()[0].get('object')]
node_fields = node_model.fields_get(cr, user, None, context)
fields.update(node_fields)
if not node.get("create") and not node_model.check_access_rights(cr, user, 'create', raise_exception=False):
node.set("create", 'false')
if node.getchildren()[1].tag == 'arrow':
arrow_fields = self.pool[node.getchildren()[1].get('object')].fields_get(cr, user, None, context)
fields.update(arrow_fields)
else:
fields = Model.fields_get(cr, user, None, context)
fields_def = self.postprocess(cr, user, model, node, view_id, False, fields, context=context)
node = self._disable_workflow_buttons(cr, user, model, node)
if node.tag in ('kanban', 'tree', 'form', 'gantt'):
for action, operation in (('create', 'create'), ('delete', 'unlink'), ('edit', 'write')):
if not node.get(action) and not Model.check_access_rights(cr, user, operation, raise_exception=False):
node.set(action, 'false')
arch = etree.tostring(node, encoding="utf-8").replace('\t', '')
for k in fields.keys():
if k not in fields_def:
del fields[k]
for field in fields_def:
if field == 'id':
# sometime, the view may contain the (invisible) field 'id' needed for a domain (when 2 objects have cross references)
fields['id'] = {'readonly': True, 'type': 'integer', 'string': 'ID'}
elif field in fields:
fields[field].update(fields_def[field])
else:
message = _("Field `%(field_name)s` does not exist") % \
dict(field_name=field)
self.raise_view_error(cr, user, message, view_id, context)
return arch, fields
#------------------------------------------------------
# QWeb template views
#------------------------------------------------------
@tools.ormcache_context(accepted_keys=('lang','inherit_branding', 'editable', 'translatable'))
def read_template(self, cr, uid, xml_id, context=None):
if '.' not in xml_id:
raise ValueError('Invalid template id: %r' % (xml_id,))
view_id = self.pool['ir.model.data'].xmlid_to_res_id(cr, uid, xml_id, raise_if_not_found=True)
arch = self.read_combined(cr, uid, view_id, fields=['arch'], context=context)['arch']
arch_tree = etree.fromstring(arch)
if 'lang' in context:
arch_tree = self.translate_qweb(cr, uid, view_id, arch_tree, context['lang'], context)
self.distribute_branding(arch_tree)
root = etree.Element('templates')
root.append(arch_tree)
arch = etree.tostring(root, encoding='utf-8', xml_declaration=True)
return arch
def clear_cache(self):
self.read_template.clear_cache(self)
def distribute_branding(self, e, branding=None, parent_xpath='',
index_map=misc.ConstantMapping(1)):
if e.get('t-ignore') or e.tag == 'head':
# TODO: find a better name and check if we have a string to boolean helper
return
node_path = e.get('data-oe-xpath')
if node_path is None:
node_path = "%s/%s[%d]" % (parent_xpath, e.tag, index_map[e.tag])
if branding and not (e.get('data-oe-model') or e.get('t-field')):
e.attrib.update(branding)
e.set('data-oe-xpath', node_path)
if not e.get('data-oe-model'): return
# if a branded element contains branded elements distribute own
# branding to children unless it's t-raw, then just remove branding
# on current element
if e.tag == 't' or 't-raw' in e.attrib or \
any(self.is_node_branded(child) for child in e.iterdescendants()):
distributed_branding = dict(
(attribute, e.attrib.pop(attribute))
for attribute in MOVABLE_BRANDING
if e.get(attribute))
if 't-raw' not in e.attrib:
# TODO: collections.Counter if remove p2.6 compat
# running index by tag type, for XPath query generation
indexes = collections.defaultdict(lambda: 0)
for child in e.iterchildren(tag=etree.Element):
indexes[child.tag] += 1
self.distribute_branding(child, distributed_branding,
parent_xpath=node_path,
index_map=indexes)
def is_node_branded(self, node):
""" Finds out whether a node is branded or qweb-active (bears a
@data-oe-model or a @t-* *which is not t-field* as t-field does not
section out views)
:param node: an etree-compatible element to test
:type node: etree._Element
:rtype: boolean
"""
return any(
(attr == 'data-oe-model' or (attr != 't-field' and attr.startswith('t-')))
for attr in node.attrib
)
def translate_qweb(self, cr, uid, id_, arch, lang, context=None):
# TODO: this should be moved in a place before inheritance is applied
# but process() is only called on fields_view_get()
Translations = self.pool['ir.translation']
h = HTMLParser.HTMLParser()
def get_trans(text):
if not text or not text.strip():
return None
text = h.unescape(text.strip())
if len(text) < 2 or (text.startswith('<!') and text.endswith('>')):
return None
return Translations._get_source(cr, uid, 'website', 'view', lang, text, id_)
if arch.tag not in ['script']:
text = get_trans(arch.text)
if text:
arch.text = arch.text.replace(arch.text.strip(), text)
tail = get_trans(arch.tail)
if tail:
arch.tail = arch.tail.replace(arch.tail.strip(), tail)
for attr_name in ('title', 'alt', 'placeholder'):
attr = get_trans(arch.get(attr_name))
if attr:
arch.set(attr_name, attr)
for node in arch.iterchildren("*"):
self.translate_qweb(cr, uid, id_, node, lang, context)
return arch
@openerp.tools.ormcache()
def get_view_xmlid(self, cr, uid, id):
imd = self.pool['ir.model.data']
domain = [('model', '=', 'ir.ui.view'), ('res_id', '=', id)]
xmlid = imd.search_read(cr, uid, domain, ['module', 'name'])[0]
return '%s.%s' % (xmlid['module'], xmlid['name'])
def render(self, cr, uid, id_or_xml_id, values=None, engine='ir.qweb', context=None):
if isinstance(id_or_xml_id, list):
id_or_xml_id = id_or_xml_id[0]
tname = id_or_xml_id
if isinstance(tname, (int, long)):
tname = self.get_view_xmlid(cr, uid, tname)
if not context:
context = {}
if values is None:
values = dict()
qcontext = dict(
keep_query=keep_query,
request=request,
json=simplejson,
quote_plus=werkzeug.url_quote_plus,
)
qcontext.update(values)
def loader(name):
return self.read_template(cr, uid, name, context=context)
return self.pool[engine].render(cr, uid, tname, qcontext, loader=loader, context=context)
#------------------------------------------------------
# Misc
#------------------------------------------------------
def graph_get(self, cr, uid, id, model, node_obj, conn_obj, src_node, des_node, label, scale, context=None):
nodes=[]
@ -305,5 +921,4 @@ class view(osv.osv):
ids = map(itemgetter(0), cr.fetchall())
return self._check_xml(cr, uid, ids)
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
# vim:et:

View File

@ -17,6 +17,7 @@
<group>
<field name="field_parent"/>
<field name="inherit_id"/>
<field name="model_data_id"/>
<field name="xml_id"/>
</group>
</group>
@ -49,17 +50,19 @@
<field name="model">ir.ui.view</field>
<field name="arch" type="xml">
<search string="Views">
<field name="name" filter_domain="['|', ('name','ilike',self), ('model','ilike',self)]" string="View"/>
<field name="name" filter_domain="['|', '|', ('name','ilike',self), ('model','ilike',self), ('model_data_id','ilike',self)]" string="View"/>
<filter string="Form" domain="[('type', '=','form')]"/>
<filter string="Tree" domain="[('type', '=', 'tree')]"/>
<filter string="Kanban" domain="[('type', '=', 'kanban')]"/>
<filter string="Search" domain="[('type', '=', 'search')]"/>
<filter string="QWeb" domain="[('type', '=', 'qweb')]"/>
<field name="model"/>
<field name="inherit_id"/>
<field name="type"/>
<group expand="0" string="Group By...">
<filter string="Object" icon="terp-stock_align_left_24" domain="[]" context="{'group_by':'model'}"/>
<filter string="Type" icon="terp-stock_symbol-selection" domain="[]" context="{'group_by':'type'}"/>
<filter string="Object" domain="[]" context="{'group_by':'model'}"/>
<filter string="Type" domain="[]" context="{'group_by':'type'}"/>
<filter string="Inherit" domain="[]" context="{'group_by':'inherit_id'}"/>
</group>
</search>
</field>

View File

@ -41,8 +41,9 @@ except ImportError:
from StringIO import StringIO # NOQA
import openerp
from openerp import modules, tools, addons
from openerp import modules, tools
from openerp.modules.db import create_categories
from openerp.modules import get_module_resource
from openerp.tools.parse_version import parse_version
from openerp.tools.translate import _
from openerp.osv import fields, osv, orm
@ -154,7 +155,7 @@ class module(osv.osv):
def _get_desc(self, cr, uid, ids, field_name=None, arg=None, context=None):
res = dict.fromkeys(ids, '')
for module in self.browse(cr, uid, ids, context=context):
path = addons.get_module_resource(module.name, 'static/description/index.html')
path = get_module_resource(module.name, 'static/description/index.html')
if path:
with tools.file_open(path, 'rb') as desc_file:
doc = desc_file.read()
@ -233,7 +234,7 @@ class module(osv.osv):
def _get_icon_image(self, cr, uid, ids, field_name=None, arg=None, context=None):
res = dict.fromkeys(ids, '')
for module in self.browse(cr, uid, ids, context=context):
path = addons.get_module_resource(module.name, 'static', 'description', 'icon.png')
path = get_module_resource(module.name, 'static', 'description', 'icon.png')
if path:
image_file = tools.file_open(path, 'rb')
try:

View File

@ -7,6 +7,7 @@
<field name="visible" eval="0" />
</record>
<record model="ir.module.category" id="module_category_localization">
<field name="name">Localization</field>
<field name="visible" eval="0" />
@ -113,6 +114,11 @@
<field name="sequence">15</field>
</record>
<record model="ir.module.category" id="module_category_website">
<field name="name">Website</field>
<field name="sequence">16</field>
</record>
<record model="ir.module.category" id="module_category_administration">
<field name="name">Administration</field>
<field name="sequence">100</field>

View File

@ -141,8 +141,8 @@ class res_company(osv.osv):
'state_id': fields.function(_get_address_data, fnct_inv=_set_address_data, type='many2one', relation='res.country.state', string="Fed. State", multi='address'),
'bank_ids': fields.one2many('res.partner.bank','company_id', 'Bank Accounts', help='Bank accounts related to this company'),
'country_id': fields.function(_get_address_data, fnct_inv=_set_address_data, type='many2one', relation='res.country', string="Country", multi='address'),
'email': fields.function(_get_address_data, fnct_inv=_set_address_data, size=64, type='char', string="Email", multi='address'),
'phone': fields.function(_get_address_data, fnct_inv=_set_address_data, size=64, type='char', string="Phone", multi='address'),
'email': fields.related('partner_id', 'email', size=64, type='char', string="Email", store=True),
'phone': fields.related('partner_id', 'phone', size=64, type='char', string="Phone", store=True),
'fax': fields.function(_get_address_data, fnct_inv=_set_address_data, size=64, type='char', string="Fax", multi='address'),
'website': fields.related('partner_id', 'website', string="Website", type="char", size=64),
'vat': fields.related('partner_id', 'vat', string="Tax ID", type="char", size=32),

View File

@ -415,6 +415,7 @@ class res_config_settings(osv.osv_memory, res_config_module_installation_mixin):
* For a boolean field like 'group_XXX', ``execute`` adds/removes 'implied_group'
to/from the implied groups of 'group', depending on the field's value.
By default 'group' is the group Employee. Groups are given by their xml id.
The attribute 'group' may contain several xml ids, separated by commas.
* For a boolean field like 'module_XXX', ``execute`` triggers the immediate
installation of the module named 'XXX' if the field has value ``True``.
@ -437,7 +438,7 @@ class res_config_settings(osv.osv_memory, res_config_module_installation_mixin):
""" return a dictionary with the fields classified by category::
{ 'default': [('default_foo', 'model', 'foo'), ...],
'group': [('group_bar', browse_group, browse_implied_group), ...],
'group': [('group_bar', [browse_group], browse_implied_group), ...],
'module': [('module_baz', browse_module), ...],
'other': ['other_field', ...],
}
@ -446,15 +447,15 @@ class res_config_settings(osv.osv_memory, res_config_module_installation_mixin):
ir_module = self.pool['ir.module.module']
def ref(xml_id):
mod, xml = xml_id.split('.', 1)
return ir_model_data.get_object(cr, uid, mod, xml, context)
return ir_model_data.get_object(cr, uid, mod, xml, context=context)
defaults, groups, modules, others = [], [], [], []
for name, field in self._columns.items():
if name.startswith('default_') and hasattr(field, 'default_model'):
defaults.append((name, field.default_model, name[8:]))
elif name.startswith('group_') and isinstance(field, fields.boolean) and hasattr(field, 'implied_group'):
field_group = getattr(field, 'group', 'base.group_user')
groups.append((name, ref(field_group), ref(field.implied_group)))
field_groups = getattr(field, 'group', 'base.group_user').split(',')
groups.append((name, map(ref, field_groups), ref(field.implied_group)))
elif name.startswith('module_') and isinstance(field, fields.boolean):
mod_ids = ir_module.search(cr, uid, [('name', '=', name[7:])])
record = ir_module.browse(cr, uid, mod_ids[0], context) if mod_ids else None
@ -477,8 +478,8 @@ class res_config_settings(osv.osv_memory, res_config_module_installation_mixin):
res[name] = value
# groups: which groups are implied by the group Employee
for name, group, implied_group in classified['group']:
res[name] = implied_group in group.implied_ids
for name, groups, implied_group in classified['group']:
res[name] = all(implied_group in group.implied_ids for group in groups)
# modules: which modules are installed/to install
for name, module in classified['module']:
@ -497,6 +498,7 @@ class res_config_settings(osv.osv_memory, res_config_module_installation_mixin):
ir_values = self.pool['ir.values']
ir_module = self.pool['ir.module.module']
res_groups = self.pool['res.groups']
classified = self._get_classified_fields(cr, uid, context)
@ -507,12 +509,16 @@ class res_config_settings(osv.osv_memory, res_config_module_installation_mixin):
ir_values.set_default(cr, SUPERUSER_ID, model, field, config[name])
# group fields: modify group / implied groups
for name, group, implied_group in classified['group']:
for name, groups, implied_group in classified['group']:
gids = map(int, groups)
if config[name]:
group.write({'implied_ids': [(4, implied_group.id)]})
res_groups.write(cr, uid, gids, {'implied_ids': [(4, implied_group.id)]}, context=context)
else:
group.write({'implied_ids': [(3, implied_group.id)]})
implied_group.write({'users': [(3, u.id) for u in group.users]})
res_groups.write(cr, uid, gids, {'implied_ids': [(3, implied_group.id)]}, context=context)
uids = set()
for group in groups:
uids.update(map(int, group.users))
implied_group.write({'users': [(3, u) for u in uids]})
# other fields: execute all methods that start with 'set_'
for method in dir(self):

Some files were not shown because too many files have changed in this diff Show More