[FIX] hide context menu. merge latest trunk.

bzr revid: vda@tinyerp.com-20111024101015-19l1vhvcvfiiwkkq
This commit is contained in:
Vaibhav (OpenERP) 2011-10-24 15:40:15 +05:30
commit 964f7c5a71
169 changed files with 15370 additions and 3200 deletions

View File

@ -9,4 +9,3 @@ RE:^include/
RE:^share/
RE:^man/
RE:^lib/
logging.cfg

View File

@ -1,28 +1,26 @@
import common
import controllers
import common.dispatch
import logging
import optparse
_logger = logging.getLogger(__name__)
class Options(object):
pass
def wsgi_postload():
import openerp.wsgi
import openerp
import os
import tempfile
_logger.info("embedded mode")
class Options(object):
pass
o = Options()
o.dbfilter = '.*'
o.dbfilter = openerp.tools.config['dbfilter']
o.server_wide_modules = openerp.conf.server_wide_modules or ['web']
o.session_storage = os.path.join(tempfile.gettempdir(), "oe-sessions")
o.addons_path = os.path.dirname(os.path.dirname(__file__))
o.addons_path = openerp.modules.module.ad_paths
o.serve_static = True
o.backend = 'local'
app = common.dispatch.Root(o)
#import openerp.wsgi
app = common.http.Root(o)
openerp.wsgi.register_wsgi_handler(app)
# TODO
# if we detect that we are imported from the openerp server register common.Root() as a wsgi entry point

View File

@ -1,7 +1,9 @@
{
"name" : "web",
"category" : "Hidden",
"depends" : [],
'active': True,
'post_load' : 'wsgi_postload',
'js' : [
"static/lib/datejs/globalization/en-US.js",
"static/lib/datejs/core.js",
@ -19,11 +21,13 @@
"static/lib/jquery.ui/js/jquery-ui-1.8.9.custom.min.js",
"static/lib/jquery.ui/js/jquery-ui-timepicker-addon.js",
"static/lib/jquery.ui.notify/js/jquery.notify.js",
"static/lib/jquery.deferred-queue/jquery.deferred-queue.js",
"static/lib/json/json2.js",
"static/lib/qweb/qweb2.js",
"static/lib/underscore/underscore.js",
"static/lib/underscore/underscore.string.js",
"static/lib/labjs/LAB.src.js",
"static/lib/py.parse/lib/py.js",
"static/src/js/boot.js",
"static/src/js/core.js",
"static/src/js/dates.js",
@ -32,6 +36,7 @@
"static/src/js/views.js",
"static/src/js/data.js",
"static/src/js/data_export.js",
"static/src/js/data_import.js",
"static/src/js/search.js",
"static/src/js/view_form.js",
"static/src/js/view_list.js",
@ -44,6 +49,6 @@
"static/lib/jquery.ui.notify/css/ui.notify.css",
"static/src/css/base.css",
"static/src/css/data_export.css",
"static/src/css/data_import.css",
],
'post_load' : 'wsgi_postload',
}

View File

@ -1,2 +1,6 @@
#!/usr/bin/python
from dispatch import *
import http
import nonliterals
import release
import session
import xml2json

View File

@ -1,48 +0,0 @@
# -*- coding: utf-8 -*-
""" Backport of Python 2.6's ast.py for Python 2.5
"""
__all__ = ['literal_eval']
try:
from ast import literal_eval
except ImportError:
from _ast import *
from _ast import __version__
def parse(expr, filename='<unknown>', mode='exec'):
"""
Parse an expression into an AST node.
Equivalent to compile(expr, filename, mode, PyCF_ONLY_AST).
"""
return compile(expr, filename, mode, PyCF_ONLY_AST)
def literal_eval(node_or_string):
"""
Safely evaluate an expression node or a string containing a Python
expression. The string or node provided may only consist of the
following Python literal structures: strings, numbers, tuples, lists,
dicts, booleans, and None.
"""
_safe_names = {'None': None, 'True': True, 'False': False}
if isinstance(node_or_string, basestring):
node_or_string = parse(node_or_string, mode='eval')
if isinstance(node_or_string, Expression):
node_or_string = node_or_string.body
def _convert(node):
if isinstance(node, Str):
return node.s
elif isinstance(node, Num):
return node.n
elif isinstance(node, Tuple):
return tuple(map(_convert, node.elts))
elif isinstance(node, List):
return list(map(_convert, node.elts))
elif isinstance(node, Dict):
return dict((_convert(k), _convert(v)) for k, v
in zip(node.keys, node.values))
elif isinstance(node, Name):
if node.id in _safe_names:
return _safe_names[node.id]
raise ValueError('malformed string')
return _convert(node_or_string)

View File

@ -1,88 +0,0 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
# Copyright (C) 2010 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
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import datetime
DEFAULT_SERVER_DATE_FORMAT = "%Y-%m-%d"
DEFAULT_SERVER_TIME_FORMAT = "%H:%M:%S"
DEFAULT_SERVER_DATETIME_FORMAT = "%s %s" % (
DEFAULT_SERVER_DATE_FORMAT,
DEFAULT_SERVER_TIME_FORMAT)
def str_to_datetime(str):
"""
Converts a string to a datetime object using OpenERP's
datetime string format (exemple: '2011-12-01 15:12:35').
No timezone information is added, the datetime is a naive instance, but
according to OpenERP 6.1 specification the timezone is always UTC.
"""
if not str:
return str
return datetime.datetime.strptime(str, DEFAULT_SERVER_DATETIME_FORMAT)
def str_to_date(str):
"""
Converts a string to a date object using OpenERP's
date string format (exemple: '2011-12-01').
"""
if not str:
return str
return datetime.datetime.strptime(str, DEFAULT_SERVER_DATE_FORMAT).date()
def str_to_time(str):
"""
Converts a string to a time object using OpenERP's
time string format (exemple: '15:12:35').
"""
if not str:
return str
return datetime.datetime.strptime(str, DEFAULT_SERVER_TIME_FORMAT).time()
def datetime_to_str(obj):
"""
Converts a datetime object to a string using OpenERP's
datetime string format (exemple: '2011-12-01 15:12:35').
The datetime instance should not have an attached timezone and be in UTC.
"""
if not obj:
return False
return obj.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
def date_to_str(obj):
"""
Converts a date object to a string using OpenERP's
date string format (exemple: '2011-12-01').
"""
if not obj:
return False
return obj.strftime(DEFAULT_SERVER_DATE_FORMAT)
def time_to_str(obj):
"""
Converts a time object to a string using OpenERP's
time string format (exemple: '15:12:35').
"""
if not obj:
return False
return obj.strftime(DEFAULT_SERVER_TIME_FORMAT)

View File

@ -1,429 +0,0 @@
#!/usr/bin/python
from __future__ import with_statement
import functools
import logging
import os
import pprint
import sys
import traceback
import uuid
import xmlrpclib
import simplejson
import werkzeug.datastructures
import werkzeug.exceptions
import werkzeug.urls
import werkzeug.utils
import werkzeug.wrappers
import werkzeug.wsgi
import ast
import nonliterals
import http
# import backendlocal as backend
import session as backend
import openerplib
__all__ = ['Root', 'jsonrequest', 'httprequest', 'Controller',
'WebRequest', 'JsonRequest', 'HttpRequest']
_logger = logging.getLogger(__name__)
#-----------------------------------------------------------
# Globals (wont move into a pool)
#-----------------------------------------------------------
applicationsession = {}
addons_module = {}
addons_manifest = {}
controllers_class = {}
controllers_object = {}
controllers_path = {}
#----------------------------------------------------------
# OpenERP Web RequestHandler
#----------------------------------------------------------
class WebRequest(object):
""" Parent class for all OpenERP Web request types, mostly deals with
initialization and setup of the request object (the dispatching itself has
to be handled by the subclasses)
:param request: a wrapped werkzeug Request object
:type request: :class:`werkzeug.wrappers.BaseRequest`
:param config: configuration object
.. attribute:: applicationsession
an application-wide :class:`~collections.Mapping`
.. attribute:: httprequest
the original :class:`werkzeug.wrappers.Request` object provided to the
request
.. attribute:: httpsession
a :class:`~collections.Mapping` holding the HTTP session data for the
current http session
.. attribute:: config
config parameter provided to the request object
.. attribute:: params
:class:`~collections.Mapping` of request parameters, not generally
useful as they're provided directly to the handler method as keyword
arguments
.. attribute:: session_id
opaque identifier for the :class:`backend.OpenERPSession` instance of
the current request
.. attribute:: session
:class:`~backend.OpenERPSession` instance for the current request
.. attribute:: context
:class:`~collections.Mapping` of context values for the current request
.. attribute:: debug
``bool``, indicates whether the debug mode is active on the client
"""
def __init__(self, request, config):
self.applicationsession = applicationsession
self.httprequest = request
self.httpresponse = None
self.httpsession = request.session
self.config = config
def init(self, params):
self.params = dict(params)
# OpenERP session setup
self.session_id = self.params.pop("session_id", None) or uuid.uuid4().hex
self.session = self.httpsession.setdefault(
self.session_id, backend.OpenERPSession(
self.config.server_host, self.config.server_port))
self.context = self.params.pop('context', None)
self.debug = self.params.pop('debug', False) != False
class JsonRequest(WebRequest):
""" JSON-RPC2 over HTTP.
Sucessful request::
--> {"jsonrpc": "2.0",
"method": "call",
"params": {"session_id": "SID",
"context": {},
"arg1": "val1" },
"id": null}
<-- {"jsonrpc": "2.0",
"result": { "res1": "val1" },
"id": null}
Request producing a error::
--> {"jsonrpc": "2.0",
"method": "call",
"params": {"session_id": "SID",
"context": {},
"arg1": "val1" },
"id": null}
<-- {"jsonrpc": "2.0",
"error": {"code": 1,
"message": "End user error message.",
"data": {"code": "codestring",
"debug": "traceback" } },
"id": null}
"""
def dispatch(self, controller, method, requestf=None, request=None):
""" Calls the method asked for by the JSON-RPC2 request
:param controller: the instance of the controller which received the request
:param method: the method which received the request
:param requestf: a file-like object containing an encoded JSON-RPC2 request
:param request: a JSON-RPC2 request
:returns: an utf8 encoded JSON-RPC2 reply
"""
response = {"jsonrpc": "2.0" }
error = None
try:
# Read POST content or POST Form Data named "request"
if requestf:
self.jsonrequest = simplejson.load(requestf, object_hook=nonliterals.non_literal_decoder)
else:
self.jsonrequest = simplejson.loads(request, object_hook=nonliterals.non_literal_decoder)
self.init(self.jsonrequest.get("params", {}))
if _logger.isEnabledFor(logging.DEBUG):
_logger.debug("--> %s.%s\n%s", controller.__class__.__name__, method.__name__, pprint.pformat(self.jsonrequest))
response['id'] = self.jsonrequest.get('id')
response["result"] = method(controller, self, **self.params)
except openerplib.AuthenticationError:
error = {
'code': 100,
'message': "OpenERP Session Invalid",
'data': {
'type': 'session_invalid',
'debug': traceback.format_exc()
}
}
except xmlrpclib.Fault, e:
error = {
'code': 200,
'message': "OpenERP Server Error",
'data': {
'type': 'server_exception',
'fault_code': e.faultCode,
'debug': "Client %s\nServer %s" % (
"".join(traceback.format_exception("", None, sys.exc_traceback)), e.faultString)
}
}
except Exception:
logging.getLogger(__name__ + '.JSONRequest.dispatch').exception\
("An error occured while handling a json request")
error = {
'code': 300,
'message': "OpenERP WebClient Error",
'data': {
'type': 'client_exception',
'debug': "Client %s" % traceback.format_exc()
}
}
if error:
response["error"] = error
if _logger.isEnabledFor(logging.DEBUG):
_logger.debug("<--\n%s", pprint.pformat(response))
content = simplejson.dumps(response, cls=nonliterals.NonLiteralEncoder)
return werkzeug.wrappers.Response(
content, headers=[('Content-Type', 'application/json'),
('Content-Length', len(content))])
def jsonrequest(f):
""" Decorator marking the decorated method as being a handler for a
JSON-RPC request (the exact request path is specified via the
``$(Controller._cp_path)/$methodname`` combination.
If the method is called, it will be provided with a :class:`JsonRequest`
instance and all ``params`` sent during the JSON-RPC request, apart from
the ``session_id``, ``context`` and ``debug`` keys (which are stripped out
beforehand)
"""
@functools.wraps(f)
def json_handler(controller, request, config):
return JsonRequest(request, config).dispatch(
controller, f, requestf=request.stream)
json_handler.exposed = True
return json_handler
class HttpRequest(WebRequest):
""" Regular GET/POST request
"""
def dispatch(self, controller, method):
params = dict(self.httprequest.args)
params.update(self.httprequest.form)
params.update(self.httprequest.files)
self.init(params)
akw = {}
for key, value in self.httprequest.args.iteritems():
if isinstance(value, basestring) and len(value) < 1024:
akw[key] = value
else:
akw[key] = type(value)
_logger.debug("%s --> %s.%s %r", self.httprequest.method, controller.__class__.__name__, method.__name__, akw)
r = method(controller, self, **self.params)
if self.debug or 1:
if isinstance(r, werkzeug.wrappers.BaseResponse):
_logger.debug('<-- %s', r)
else:
_logger.debug("<-- size: %s", len(r))
return r
def make_response(self, data, headers=None, cookies=None):
""" Helper for non-HTML responses, or HTML responses with custom
response headers or cookies.
While handlers can just return the HTML markup of a page they want to
send as a string if non-HTML data is returned they need to create a
complete response object, or the returned data will not be correctly
interpreted by the clients.
:param basestring data: response body
:param headers: HTTP headers to set on the response
:type headers: ``[(name, value)]``
:param collections.Mapping cookies: cookies to set on the client
"""
response = werkzeug.wrappers.Response(data, headers=headers)
if cookies:
for k, v in cookies.iteritems():
response.set_cookie(k, v)
return response
def not_found(self, description=None):
""" Helper for 404 response, return its result from the method
"""
return werkzeug.exceptions.NotFound(description)
def httprequest(f):
""" Decorator marking the decorated method as being a handler for a
normal HTTP request (the exact request path is specified via the
``$(Controller._cp_path)/$methodname`` combination.
If the method is called, it will be provided with a :class:`HttpRequest`
instance and all ``params`` sent during the request (``GET`` and ``POST``
merged in the same dictionary), apart from the ``session_id``, ``context``
and ``debug`` keys (which are stripped out beforehand)
"""
@functools.wraps(f)
def http_handler(controller, request, config):
return HttpRequest(request, config).dispatch(controller, f)
http_handler.exposed = True
return http_handler
class ControllerType(type):
def __init__(cls, name, bases, attrs):
super(ControllerType, cls).__init__(name, bases, attrs)
controllers_class["%s.%s" % (cls.__module__, cls.__name__)] = cls
class Controller(object):
__metaclass__ = ControllerType
class Root(object):
"""Root WSGI application for the OpenERP Web Client.
:param options: mandatory initialization options object, must provide
the following attributes:
``server_host`` (``str``)
hostname of the OpenERP server to dispatch RPC to
``server_port`` (``int``)
RPC port of the OpenERP server
``serve_static`` (``bool | None``)
whether this application should serve the various
addons's static files
``storage_path`` (``str``)
filesystem path where HTTP session data will be stored
``dbfilter`` (``str``)
only used in case the list of databases is requested
by the server, will be filtered by this pattern
"""
def __init__(self, options):
self.root = werkzeug.urls.Href('/web/webclient/home')
self.config = options
self.session_cookie = 'sessionid'
self.addons = {}
static_dirs = self._load_addons()
if options.serve_static:
self.dispatch = werkzeug.wsgi.SharedDataMiddleware(
self.dispatch, static_dirs)
if options.session_storage:
if not os.path.exists(options.session_storage):
os.mkdir(options.session_storage, 0700)
self.session_storage = options.session_storage
def __call__(self, environ, start_response):
""" Handle a WSGI request
"""
return self.dispatch(environ, start_response)
def dispatch(self, environ, start_response):
"""
Performs the actual WSGI dispatching for the application, may be
wrapped during the initialization of the object.
Call the object directly.
"""
request = werkzeug.wrappers.Request(environ)
request.parameter_storage_class = werkzeug.datastructures.ImmutableDict
if request.path == '/':
return werkzeug.utils.redirect(
self.root(dict(request.args, debug='')), 301)(
environ, start_response)
elif request.path == '/mobile':
return werkzeug.utils.redirect(
'/web_mobile/static/src/web_mobile.html', 301)(
environ, start_response)
handler = self.find_handler(*(request.path.split('/')[1:]))
if not handler:
response = werkzeug.exceptions.NotFound()
else:
with http.session(request, self.session_storage, self.session_cookie) as session:
result = handler(
request, self.config)
if isinstance(result, basestring):
response = werkzeug.wrappers.Response(
result, headers=[('Content-Type', 'text/html; charset=utf-8'),
('Content-Length', len(result))])
else:
response = result
response.set_cookie(self.session_cookie, session.sid)
return response(environ, start_response)
def _load_addons(self):
"""
Loads all addons at the specified addons path, returns a mapping of
static URLs to the corresponding directories
"""
statics = {}
addons_path = self.config.addons_path
if addons_path not in sys.path:
sys.path.insert(0, addons_path)
for module in os.listdir(addons_path):
if module not in addons_module:
manifest_path = os.path.join(addons_path, module, '__openerp__.py')
if os.path.isfile(manifest_path):
manifest = ast.literal_eval(open(manifest_path).read())
_logger.info("Loading %s", module)
m = __import__(module)
addons_module[module] = m
addons_manifest[module] = manifest
statics['/%s/static' % module] = \
os.path.join(addons_path, module, 'static')
for k, v in controllers_class.items():
if k not in controllers_object:
o = v()
controllers_object[k] = o
if hasattr(o, '_cp_path'):
controllers_path[o._cp_path] = o
return statics
def find_handler(self, *l):
"""
Tries to discover the controller handling the request for the path
specified by the provided parameters
:param l: path sections to a controller or controller method
:returns: a callable matching the path sections, or ``None``
:rtype: ``Controller | None``
"""
if len(l) > 1:
for i in range(len(l), 1, -1):
ps = "/" + "/".join(l[0:i])
if ps in controllers_path:
c = controllers_path[ps]
rest = l[i:] or ['index']
meth = rest[0]
m = getattr(c, meth)
if getattr(m, 'exposed', False):
_logger.debug("Dispatching to %s %s %s", ps, c, meth)
return m
return None

View File

@ -1,13 +1,286 @@
# -*- coding: utf-8 -*-
#----------------------------------------------------------
# OpenERP Web HTTP layer
#----------------------------------------------------------
import ast
import contextlib
import functools
import logging
import urllib
import os
import pprint
import sys
import traceback
import uuid
import xmlrpclib
import simplejson
import werkzeug.contrib.sessions
import werkzeug.datastructures
import werkzeug.exceptions
import werkzeug.utils
import werkzeug.wrappers
import werkzeug.wsgi
import nonliterals
import session
import openerplib
__all__ = ['Root', 'jsonrequest', 'httprequest', 'Controller',
'WebRequest', 'JsonRequest', 'HttpRequest']
_logger = logging.getLogger(__name__)
#----------------------------------------------------------
# OpenERP Web RequestHandler
#----------------------------------------------------------
class WebRequest(object):
""" Parent class for all OpenERP Web request types, mostly deals with
initialization and setup of the request object (the dispatching itself has
to be handled by the subclasses)
:param request: a wrapped werkzeug Request object
:type request: :class:`werkzeug.wrappers.BaseRequest`
:param config: configuration object
.. attribute:: httprequest
the original :class:`werkzeug.wrappers.Request` object provided to the
request
.. attribute:: httpsession
a :class:`~collections.Mapping` holding the HTTP session data for the
current http session
.. attribute:: config
config parameter provided to the request object
.. attribute:: params
:class:`~collections.Mapping` of request parameters, not generally
useful as they're provided directly to the handler method as keyword
arguments
.. attribute:: session_id
opaque identifier for the :class:`session.OpenERPSession` instance of
the current request
.. attribute:: session
:class:`~session.OpenERPSession` instance for the current request
.. attribute:: context
:class:`~collections.Mapping` of context values for the current request
.. attribute:: debug
``bool``, indicates whether the debug mode is active on the client
"""
def __init__(self, request, config):
self.httprequest = request
self.httpresponse = None
self.httpsession = request.session
self.config = config
def init(self, params):
self.params = dict(params)
# OpenERP session setup
self.session_id = self.params.pop("session_id", None) or uuid.uuid4().hex
self.session = self.httpsession.setdefault(self.session_id, session.OpenERPSession())
self.session.config = self.config
self.context = self.params.pop('context', None)
self.debug = self.params.pop('debug', False) != False
class JsonRequest(WebRequest):
""" JSON-RPC2 over HTTP.
Sucessful request::
--> {"jsonrpc": "2.0",
"method": "call",
"params": {"session_id": "SID",
"context": {},
"arg1": "val1" },
"id": null}
<-- {"jsonrpc": "2.0",
"result": { "res1": "val1" },
"id": null}
Request producing a error::
--> {"jsonrpc": "2.0",
"method": "call",
"params": {"session_id": "SID",
"context": {},
"arg1": "val1" },
"id": null}
<-- {"jsonrpc": "2.0",
"error": {"code": 1,
"message": "End user error message.",
"data": {"code": "codestring",
"debug": "traceback" } },
"id": null}
"""
def dispatch(self, controller, method, requestf=None, request=None):
""" Calls the method asked for by the JSON-RPC2 request
:param controller: the instance of the controller which received the request
:param method: the method which received the request
:param requestf: a file-like object containing an encoded JSON-RPC2 request
:param request: a JSON-RPC2 request
:returns: an utf8 encoded JSON-RPC2 reply
"""
response = {"jsonrpc": "2.0" }
error = None
try:
# Read POST content or POST Form Data named "request"
if requestf:
self.jsonrequest = simplejson.load(requestf, object_hook=nonliterals.non_literal_decoder)
else:
self.jsonrequest = simplejson.loads(request, object_hook=nonliterals.non_literal_decoder)
self.init(self.jsonrequest.get("params", {}))
if _logger.isEnabledFor(logging.DEBUG):
_logger.debug("--> %s.%s\n%s", controller.__class__.__name__, method.__name__, pprint.pformat(self.jsonrequest))
response['id'] = self.jsonrequest.get('id')
response["result"] = method(controller, self, **self.params)
except openerplib.AuthenticationError:
error = {
'code': 100,
'message': "OpenERP Session Invalid",
'data': {
'type': 'session_invalid',
'debug': traceback.format_exc()
}
}
except xmlrpclib.Fault, e:
error = {
'code': 200,
'message': "OpenERP Server Error",
'data': {
'type': 'server_exception',
'fault_code': e.faultCode,
'debug': "Client %s\nServer %s" % (
"".join(traceback.format_exception("", None, sys.exc_traceback)), e.faultString)
}
}
except Exception:
logging.getLogger(__name__ + '.JSONRequest.dispatch').exception\
("An error occured while handling a json request")
error = {
'code': 300,
'message': "OpenERP WebClient Error",
'data': {
'type': 'client_exception',
'debug': "Client %s" % traceback.format_exc()
}
}
if error:
response["error"] = error
if _logger.isEnabledFor(logging.DEBUG):
_logger.debug("<--\n%s", pprint.pformat(response))
content = simplejson.dumps(response, cls=nonliterals.NonLiteralEncoder)
return werkzeug.wrappers.Response(
content, headers=[('Content-Type', 'application/json'),
('Content-Length', len(content))])
def jsonrequest(f):
""" Decorator marking the decorated method as being a handler for a
JSON-RPC request (the exact request path is specified via the
``$(Controller._cp_path)/$methodname`` combination.
If the method is called, it will be provided with a :class:`JsonRequest`
instance and all ``params`` sent during the JSON-RPC request, apart from
the ``session_id``, ``context`` and ``debug`` keys (which are stripped out
beforehand)
"""
@functools.wraps(f)
def json_handler(controller, request, config):
return JsonRequest(request, config).dispatch(
controller, f, requestf=request.stream)
json_handler.exposed = True
return json_handler
class HttpRequest(WebRequest):
""" Regular GET/POST request
"""
def dispatch(self, controller, method):
params = dict(self.httprequest.args)
params.update(self.httprequest.form)
params.update(self.httprequest.files)
self.init(params)
akw = {}
for key, value in self.httprequest.args.iteritems():
if isinstance(value, basestring) and len(value) < 1024:
akw[key] = value
else:
akw[key] = type(value)
_logger.debug("%s --> %s.%s %r", self.httprequest.method, controller.__class__.__name__, method.__name__, akw)
r = method(controller, self, **self.params)
if self.debug or 1:
if isinstance(r, (werkzeug.wrappers.BaseResponse, werkzeug.exceptions.HTTPException)):
_logger.debug('<-- %s', r)
else:
_logger.debug("<-- size: %s", len(r))
return r
def make_response(self, data, headers=None, cookies=None):
""" Helper for non-HTML responses, or HTML responses with custom
response headers or cookies.
While handlers can just return the HTML markup of a page they want to
send as a string if non-HTML data is returned they need to create a
complete response object, or the returned data will not be correctly
interpreted by the clients.
:param basestring data: response body
:param headers: HTTP headers to set on the response
:type headers: ``[(name, value)]``
:param collections.Mapping cookies: cookies to set on the client
"""
response = werkzeug.wrappers.Response(data, headers=headers)
if cookies:
for k, v in cookies.iteritems():
response.set_cookie(k, v)
return response
def not_found(self, description=None):
""" Helper for 404 response, return its result from the method
"""
return werkzeug.exceptions.NotFound(description)
def httprequest(f):
""" Decorator marking the decorated method as being a handler for a
normal HTTP request (the exact request path is specified via the
``$(Controller._cp_path)/$methodname`` combination.
If the method is called, it will be provided with a :class:`HttpRequest`
instance and all ``params`` sent during the request (``GET`` and ``POST``
merged in the same dictionary), apart from the ``session_id``, ``context``
and ``debug`` keys (which are stripped out beforehand)
"""
@functools.wraps(f)
def http_handler(controller, request, config):
return HttpRequest(request, config).dispatch(controller, f)
http_handler.exposed = True
return http_handler
#----------------------------------------------------------
# OpenERP Web werkzeug Session Managment wraped using with
#----------------------------------------------------------
STORES = {}
@contextlib.contextmanager
def session(request, storage_path, session_cookie='sessionid'):
def session_context(request, storage_path, session_cookie='sessionid'):
session_store = STORES.get(storage_path)
if not session_store:
session_store = werkzeug.contrib.sessions.FilesystemSessionStore(
@ -23,4 +296,188 @@ def session(request, storage_path, session_cookie='sessionid'):
try:
yield request.session
finally:
# Remove all OpenERPSession instances with no uid, they're generated
# either by login process or by HTTP requests without an OpenERP
# session id, and are generally noise
for key, value in request.session.items():
if isinstance(value, session.OpenERPSession) and not value._uid:
del request.session[key]
# FIXME: remove this when non-literals disappear
if sid:
# Re-load sessions from storage and merge non-literal
# contexts and domains (they're indexed by hash of the
# content so conflicts should auto-resolve), otherwise if
# two requests alter those concurrently the last to finish
# will overwrite the previous one, leading to loss of data
# (a non-literal is lost even though it was sent to the
# client and client errors)
#
# note that domains_store and contexts_store are append-only (we
# only ever add items to them), so we can just update one with the
# other to get the right result, if we want to merge the
# ``context`` dict we'll need something smarter
in_store = session_store.get(sid)
for k, v in request.session.iteritems():
stored = in_store.get(k)
if stored and isinstance(v, session.OpenERPSession)\
and v != stored:
v.contexts_store.update(stored.contexts_store)
v.domains_store.update(stored.domains_store)
session_store.save(request.session)
#----------------------------------------------------------
# OpenERP Web Module/Controller Loading and URL Routing
#----------------------------------------------------------
addons_module = {}
addons_manifest = {}
controllers_class = {}
controllers_object = {}
controllers_path = {}
class ControllerType(type):
def __init__(cls, name, bases, attrs):
super(ControllerType, cls).__init__(name, bases, attrs)
controllers_class["%s.%s" % (cls.__module__, cls.__name__)] = cls
class Controller(object):
__metaclass__ = ControllerType
class Root(object):
"""Root WSGI application for the OpenERP Web Client.
:param options: mandatory initialization options object, must provide
the following attributes:
``server_host`` (``str``)
hostname of the OpenERP server to dispatch RPC to
``server_port`` (``int``)
RPC port of the OpenERP server
``serve_static`` (``bool | None``)
whether this application should serve the various
addons's static files
``storage_path`` (``str``)
filesystem path where HTTP session data will be stored
``dbfilter`` (``str``)
only used in case the list of databases is requested
by the server, will be filtered by this pattern
"""
def __init__(self, options):
self.root = '/web/webclient/home'
self.config = options
if self.config.backend == 'local':
conn = openerplib.get_connector(protocol='local')
else:
conn = openerplib.get_connector(hostname=self.config.server_host,
port=self.config.server_port)
self.config.connector = conn
self.session_cookie = 'sessionid'
self.addons = {}
static_dirs = self._load_addons()
if options.serve_static:
self.dispatch = werkzeug.wsgi.SharedDataMiddleware(
self.dispatch, static_dirs)
if options.session_storage:
if not os.path.exists(options.session_storage):
os.mkdir(options.session_storage, 0700)
self.session_storage = options.session_storage
def __call__(self, environ, start_response):
""" Handle a WSGI request
"""
return self.dispatch(environ, start_response)
def dispatch(self, environ, start_response):
"""
Performs the actual WSGI dispatching for the application, may be
wrapped during the initialization of the object.
Call the object directly.
"""
request = werkzeug.wrappers.Request(environ)
request.parameter_storage_class = werkzeug.datastructures.ImmutableDict
if request.path == '/':
params = urllib.urlencode(dict(request.args, debug=''))
return werkzeug.utils.redirect(self.root + '?' + params, 301)(
environ, start_response)
elif request.path == '/mobile':
return werkzeug.utils.redirect(
'/web_mobile/static/src/web_mobile.html', 301)(environ, start_response)
handler = self.find_handler(*(request.path.split('/')[1:]))
if not handler:
response = werkzeug.exceptions.NotFound()
else:
with session_context(request, self.session_storage, self.session_cookie) as session:
result = handler( request, self.config)
if isinstance(result, basestring):
headers=[('Content-Type', 'text/html; charset=utf-8'), ('Content-Length', len(result))]
response = werkzeug.wrappers.Response(result, headers=headers)
else:
response = result
if hasattr(response, 'set_cookie'):
response.set_cookie(self.session_cookie, session.sid)
return response(environ, start_response)
def _load_addons(self):
"""
Loads all addons at the specified addons path, returns a mapping of
static URLs to the corresponding directories
"""
statics = {}
for addons_path in self.config.addons_path:
if addons_path not in sys.path:
sys.path.insert(0, addons_path)
for module in os.listdir(addons_path):
if module not in addons_module:
manifest_path = os.path.join(addons_path, module, '__openerp__.py')
path_static = os.path.join(addons_path, module, 'static')
if os.path.isfile(manifest_path) and os.path.isdir(path_static):
manifest = ast.literal_eval(open(manifest_path).read())
manifest['addons_path'] = addons_path
_logger.info("Loading %s", module)
m = __import__(module)
addons_module[module] = m
addons_manifest[module] = manifest
statics['/%s/static' % module] = path_static
for k, v in controllers_class.items():
if k not in controllers_object:
o = v()
controllers_object[k] = o
if hasattr(o, '_cp_path'):
controllers_path[o._cp_path] = o
return statics
def find_handler(self, *l):
"""
Tries to discover the controller handling the request for the path
specified by the provided parameters
:param l: path sections to a controller or controller method
:returns: a callable matching the path sections, or ``None``
:rtype: ``Controller | None``
"""
if len(l):
for i in range(len(l), 0, -1):
ps = "/" + "/".join(l[0:i])
if ps in controllers_path:
c = controllers_path[ps]
rest = l[i:] or ['index']
meth = rest[0]
m = getattr(c, meth)
if getattr(m, 'exposed', False):
_logger.debug("Dispatching to %s %s %s", ps, c, meth)
return m
return None
#

View File

@ -21,12 +21,14 @@ class NonLiteralEncoder(simplejson.encoder.JSONEncoder):
if isinstance(object, Domain):
return {
'__ref': 'domain',
'__id': object.key
'__id': object.key,
'__debug': object.get_domain_string()
}
elif isinstance(object, Context):
return {
'__ref': 'context',
'__id': object.key
'__id': object.key,
'__debug': object.get_context_string()
}
elif isinstance(object, CompoundDomain):
return {
@ -41,6 +43,9 @@ class NonLiteralEncoder(simplejson.encoder.JSONEncoder):
'__eval_context': object.get_eval_context()
}
raise TypeError('Could not encode unknown non-literal %s' % object)
_ALLOWED_KEYS = frozenset(['__ref', "__id", '__domains', '__debug',
'__contexts', '__eval_context', 'own_values'])
def non_literal_decoder(dct):
""" Decodes JSON dicts into :class:`Domain` and :class:`Context` based on
@ -50,6 +55,9 @@ def non_literal_decoder(dct):
``own_values`` dict key.
"""
if '__ref' in dct:
for x in dct:
if x not in _ALLOWED_KEYS:
raise ValueError("'%s' key not allowed in non literal domain/context" % x)
if dct['__ref'] == 'domain':
domain = Domain(None, key=dct['__id'])
if 'own_values' in dct:
@ -125,7 +133,10 @@ class Domain(BaseDomain):
ctx = self.session.evaluation_context(context)
if self.own:
ctx.update(self.own)
return eval(self.get_domain_string(), SuperDict(ctx))
try:
return eval(self.get_domain_string(), SuperDict(ctx))
except NameError as e:
raise ValueError('Error during evaluation of this domain: "%s", message: "%s"' % (self.get_domain_string(), e.message))
class Context(BaseContext):
def __init__(self, session, context_string=None, key=None):
@ -170,7 +181,10 @@ class Context(BaseContext):
ctx = self.session.evaluation_context(context)
if self.own:
ctx.update(self.own)
return eval(self.get_context_string(), SuperDict(ctx))
try:
return eval(self.get_context_string(), SuperDict(ctx))
except NameError as e:
raise ValueError('Error during evaluation of this context: "%s", message: "%s"' % (self.get_context_string(), e.message))
class SuperDict(dict):
def __getattr__(self, name):
@ -193,6 +207,11 @@ class CompoundDomain(BaseDomain):
self.add(domain)
def evaluate(self, context=None):
ctx = dict(context or {})
eval_context = self.get_eval_context()
if eval_context:
eval_context = self.session.eval_context(eval_context)
ctx.update(eval_context)
final_domain = []
for domain in self.domains:
if not isinstance(domain, (list, BaseDomain)):
@ -202,9 +221,6 @@ class CompoundDomain(BaseDomain):
if isinstance(domain, list):
final_domain.extend(domain)
continue
ctx = dict(context or {})
ctx.update(self.get_eval_context() or {})
domain.session = self.session
final_domain.extend(domain.evaluate(ctx))
@ -231,7 +247,10 @@ class CompoundContext(BaseContext):
def evaluate(self, context=None):
ctx = dict(context or {})
ctx.update(self.get_eval_context() or {})
eval_context = self.get_eval_context()
if eval_context:
eval_context = self.session.eval_context(eval_context)
ctx.update(eval_context)
final_context = {}
for context_to_eval in self.contexts:
if not isinstance(context_to_eval, (dict, BaseContext)):

View File

@ -38,6 +38,7 @@ Code repository: https://code.launchpad.net/~niv-openerp/openerp-client-lib/trun
import xmlrpclib
import logging
import socket
import sys
try:
import cPickle as pickle
@ -54,6 +55,33 @@ _logger = logging.getLogger(__name__)
def _getChildLogger(logger, subname):
return logging.getLogger(logger.name + "." + subname)
#----------------------------------------------------------
# Exceptions
# TODO openerplib should raise those instead of xmlrpc faults:
#----------------------------------------------------------
class LibException(Exception):
""" Base of all client lib exceptions """
def __init__(self,code=None,message=None):
self.code = code
self.message = message
class ApplicationError(LibException):
""" maps to code: 1, server side: Exception or openerp.exceptions.DeferredException"""
class Warning(LibException):
""" maps to code: 2, server side: openerp.exceptions.Warning"""
class AccessError(LibException):
""" maps to code: 3, server side: openerp.exceptions.AccessError"""
class AccessDenied(LibException):
""" maps to code: 4, server side: openerp.exceptions.AccessDenied"""
#----------------------------------------------------------
# Connectors
#----------------------------------------------------------
class Connector(object):
"""
The base abstract class representing a connection to an OpenERP Server.
@ -70,6 +98,14 @@ class Connector(object):
self.hostname = hostname
self.port = port
def get_service(self, service_name):
"""
Returns a Service instance to allow easy manipulation of one of the services offered by the remote server.
:param service_name: The name of the service.
"""
return Service(self, service_name)
class XmlRPCConnector(Connector):
"""
A type of connector that uses the XMLRPC protocol.
@ -90,6 +126,7 @@ class XmlRPCConnector(Connector):
def send(self, service_name, method, *args):
url = '%s/%s' % (self.url, service_name)
service = xmlrpclib.ServerProxy(url)
# TODO should try except and wrap exception into LibException
return getattr(service, method)(*args)
class NetRPC_Exception(Exception):
@ -190,6 +227,47 @@ class NetRPCConnector(Connector):
socket.disconnect()
return result
class LocalConnector(Connector):
"""
A type of connector that uses the XMLRPC protocol.
"""
PROTOCOL = 'local'
__logger = _getChildLogger(_logger, 'connector.local')
def __init__(self):
pass
def send(self, service_name, method, *args):
import openerp
import traceback
try:
result = openerp.netsvc.dispatch_rpc(service_name, method, args)
except Exception,e:
# TODO change the except to raise LibException instead of their emulated xmlrpc fault
if isinstance(e, openerp.osv.osv.except_osv):
fault = xmlrpclib.Fault('warning -- ' + e.name + '\n\n' + e.value, '')
elif isinstance(e, openerp.exceptions.Warning):
fault = xmlrpclib.Fault('warning -- Warning\n\n' + str(e), '')
elif isinstance(e, openerp.exceptions.AccessError):
fault = xmlrpclib.Fault('warning -- AccessError\n\n' + str(e), '')
elif isinstance(e, openerp.exceptions.AccessDenied):
fault = xmlrpclib.Fault('AccessDenied', str(e))
elif isinstance(e, openerp.exceptions.DeferredException):
info = e.traceback
formatted_info = "".join(traceback.format_exception(*info))
fault = xmlrpclib.Fault(openerp.tools.ustr(e.message), formatted_info)
else:
info = sys.exc_info()
formatted_info = "".join(traceback.format_exception(*info))
fault = xmlrpclib.Fault(openerp.tools.exception_to_unicode(e), formatted_info)
raise fault
return result
#----------------------------------------------------------
# Public api
#----------------------------------------------------------
class Service(object):
"""
A class to execute RPC calls on a specific service of the remote server.
@ -272,7 +350,7 @@ class Connection(object):
return
if not self.database or not self.login or self.password is None:
raise AuthenticationError("Creditentials not provided")
raise AuthenticationError("Credentials not provided")
self.user_id = self.get_service("common").login(self.database, self.login, self.password)
if not self.user_id:
@ -295,7 +373,7 @@ class Connection(object):
:param service_name: The name of the service.
"""
return Service(self.connector, service_name)
return self.connector.get_service(service_name)
class AuthenticationError(Exception):
"""
@ -342,7 +420,7 @@ class Model(object):
index = {}
for r in result:
index[r['id']] = r
result = [index[x] for x in args[0]]
result = [index[x] for x in args[0] if x in index]
self.__logger.debug('result: %r', result)
return result
return proxy
@ -363,7 +441,7 @@ class Model(object):
records = self.read(record_ids, fields or [], context or {})
return records
def get_connector(hostname, protocol="xmlrpc", port="auto"):
def get_connector(hostname=None, protocol="xmlrpc", port="auto"):
"""
A shortcut method to easily create a connector to a remote server using XMLRPC or NetRPC.
@ -377,10 +455,12 @@ def get_connector(hostname, protocol="xmlrpc", port="auto"):
return XmlRPCConnector(hostname, port)
elif protocol == "netrpc":
return NetRPCConnector(hostname, port)
elif protocol == "local":
return LocalConnector()
else:
raise ValueError("You must choose xmlrpc or netrpc")
raise ValueError("You must choose xmlrpc or netrpc or local")
def get_connection(hostname, protocol="xmlrpc", port='auto', database=None,
def get_connection(hostname=None, protocol="xmlrpc", port='auto', database=None,
login=None, password=None, user_id=None):
"""
A shortcut method to easily create a connection to a remote OpenERP server.

View File

@ -1,14 +1,16 @@
#!/usr/bin/python
import datetime
import dateutil.relativedelta
import logging
import time
import openerplib
import nonliterals
_logger = logging.getLogger(__name__)
#----------------------------------------------------------
# OpenERPSession RPC openerp backend access
#----------------------------------------------------------
class OpenERPSession(object):
"""
An OpenERP RPC session, a given user can own multiple such sessions
@ -26,25 +28,26 @@ class OpenERPSession(object):
Used to store references to non-literal domains which need to be
round-tripped to the client browser.
"""
def __init__(self, server='127.0.0.1', port=8069):
self._server = server
self._port = port
def __init__(self):
self.config = None
self._db = False
self._uid = False
self._login = False
self._password = False
self._locale = 'en_US'
self.context = {}
self.contexts_store = {}
self.domains_store = {}
self._lang = {}
self.remote_timezone = 'utc'
self.client_timezone = False
def __getstate__(self):
state = dict(self.__dict__)
if "config" in state:
del state['config']
return state
def build_connection(self):
return openerplib.get_connection(hostname=self._server, port=self._port,
database=self._db, login=self._login,
user_id=self._uid, password=self._password)
conn = openerplib.Connection(self.config.connector, database=self._db, login=self._login,
user_id=self._uid, password=self._password)
return conn
def proxy(self, service):
return self.build_connection().get_service(service)
@ -99,15 +102,6 @@ class OpenERPSession(object):
self.context = self.model('res.users').context_get(self.context)
self.context = self.context or {}
self.client_timezone = self.context.get("tz", False)
# invalid code, anyway we decided the server will be in UTC
#if self.client_timezone:
# self.remote_timezone = self.execute('common', 'timezone_get')
self._locale = self.context.get('lang','en_US')
lang_ids = self.execute('res.lang','search', [('code', '=', self._locale)])
if lang_ids:
self._lang = self.execute('res.lang', 'read',lang_ids[0], [])
return self.context
@property

View File

@ -0,0 +1,38 @@
# xml2json-direct
# Simple and straightforward XML-to-JSON converter in Python
# New BSD Licensed
#
# URL: http://code.google.com/p/xml2json-direct/
class Xml2Json(object):
@staticmethod
def convert_to_json(s):
return simplejson.dumps(
Xml2Json.convert_to_structure(s), sort_keys=True, indent=4)
@staticmethod
def convert_to_structure(s):
root = ElementTree.fromstring(s)
return Xml2Json.convert_element(root)
@staticmethod
def convert_element(el, skip_whitespaces=True):
res = {}
if el.tag[0] == "{":
ns, name = el.tag.rsplit("}", 1)
res["tag"] = name
res["namespace"] = ns[1:]
else:
res["tag"] = el.tag
res["attrs"] = {}
for k, v in el.items():
res["attrs"][k] = v
kids = []
if el.text and (not skip_whitespaces or el.text.strip() != ''):
kids.append(el.text)
for kid in el:
kids.append(Xml2Json.convert_element(kid))
if kid.tail and (not skip_whitespaces or kid.tail.strip() != ''):
kids.append(kid.tail)
res["children"] = kids
return res

View File

@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
import ast
import base64
import csv
import glob
@ -8,76 +9,22 @@ import operator
import os
import re
import simplejson
import textwrap
import xmlrpclib
import time
import xmlrpclib
import zlib
from xml.etree import ElementTree
from cStringIO import StringIO
from babel.messages.pofile import read_po
import babel.messages.pofile
import web.common.dispatch as openerpweb
import web.common.ast
import web.common.nonliterals
import web.common.release
openerpweb.ast = web.common.ast
openerpweb.nonliterals = web.common.nonliterals
# Should move to openerpweb.Xml2Json
class Xml2Json:
# xml2json-direct
# Simple and straightforward XML-to-JSON converter in Python
# New BSD Licensed
#
# URL: http://code.google.com/p/xml2json-direct/
@staticmethod
def convert_to_json(s):
return simplejson.dumps(
Xml2Json.convert_to_structure(s), sort_keys=True, indent=4)
@staticmethod
def convert_to_structure(s):
root = ElementTree.fromstring(s)
return Xml2Json.convert_element(root)
@staticmethod
def convert_element(el, skip_whitespaces=True):
res = {}
if el.tag[0] == "{":
ns, name = el.tag.rsplit("}", 1)
res["tag"] = name
res["namespace"] = ns[1:]
else:
res["tag"] = el.tag
res["attrs"] = {}
for k, v in el.items():
res["attrs"][k] = v
kids = []
if el.text and (not skip_whitespaces or el.text.strip() != ''):
kids.append(el.text)
for kid in el:
kids.append(Xml2Json.convert_element(kid))
if kid.tail and (not skip_whitespaces or kid.tail.strip() != ''):
kids.append(kid.tail)
res["children"] = kids
return res
import web.common
openerpweb = web.common.http
#----------------------------------------------------------
# OpenERP Web web Controllers
#----------------------------------------------------------
def manifest_glob(addons_path, addons, key):
files = []
for addon in addons:
globlist = openerpweb.addons_manifest.get(addon, {}).get(key, [])
for pattern in globlist:
for path in glob.glob(os.path.join(addons_path, addon, pattern)):
files.append(path[len(addons_path):])
return files
def concat_files(addons_path, file_list):
def concat_files(file_list):
""" Concatenate file content
return (concat,timestamp)
concat: concatenation of file content
@ -85,8 +32,7 @@ def concat_files(addons_path, file_list):
"""
files_content = []
files_timestamp = 0
for i in file_list:
fname = os.path.join(addons_path, i[1:])
for fname in file_list:
ftime = os.path.getmtime(fname)
if ftime > files_timestamp:
files_timestamp = ftime
@ -94,66 +40,88 @@ def concat_files(addons_path, file_list):
files_concat = "".join(files_content)
return files_concat,files_timestamp
home_template = textwrap.dedent("""<!DOCTYPE html>
html_template = """<!DOCTYPE html>
<html style="height: 100%%">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>OpenERP</title>
<link rel="shortcut icon" href="/web/static/src/img/favicon.ico" type="image/x-icon"/>
%(css)s
%(javascript)s
%(js)s
<script type="text/javascript">
$(function() {
var c = new openerp.init();
var wc = new c.web.WebClient("oe");
wc.start();
var s = new openerp.init(%(modules)s);
%(init)s
});
</script>
</head>
<body id="oe" class="openerp"></body>
</html>
""")
"""
class WebClient(openerpweb.Controller):
_cp_path = "/web/webclient"
@openerpweb.jsonrequest
def csslist(self, req, mods='web'):
return manifest_glob(req.config.addons_path, mods.split(','), 'css')
def server_wide_modules(self, req):
addons = [i for i in req.config.server_wide_modules if i in openerpweb.addons_manifest]
return addons
def manifest_glob(self, req, addons, key):
if addons is None:
addons = self.server_wide_modules(req)
else:
addons = addons.split(',')
for addon in addons:
manifest = openerpweb.addons_manifest.get(addon, None)
if not manifest:
continue
# ensure does not ends with /
addons_path = os.path.join(manifest['addons_path'], '')[:-1]
globlist = manifest.get(key, [])
for pattern in globlist:
for path in glob.glob(os.path.normpath(os.path.join(addons_path, addon, pattern))):
yield path, path[len(addons_path):]
def manifest_list(self, req, mods, extension):
if not req.debug:
path = '/web/webclient/' + extension
if mods is not None:
path += '?mods=' + mods
return [path]
return ['%s?debug=%s' % (wp, os.path.getmtime(fp)) for fp, wp in self.manifest_glob(req, mods, extension)]
@openerpweb.jsonrequest
def jslist(self, req, mods='web'):
return manifest_glob(req.config.addons_path, mods.split(','), 'js')
def csslist(self, req, mods=None):
return self.manifest_list(req, mods, 'css')
@openerpweb.jsonrequest
def jslist(self, req, mods=None):
return self.manifest_list(req, mods, 'js')
@openerpweb.httprequest
def css(self, req, mods='web'):
files = manifest_glob(req.config.addons_path, mods.split(','), 'css')
content,timestamp = concat_files(req.config.addons_path, files)
# TODO request set the Date of last modif and Etag
def css(self, req, mods=None):
files = [f[0] for f in self.manifest_glob(req, mods, 'css')]
content,timestamp = concat_files(files)
# TODO use timestamp to set Last mofified date and E-tag
return req.make_response(content, [('Content-Type', 'text/css')])
@openerpweb.httprequest
def js(self, req, mods='web'):
files = manifest_glob(req.config.addons_path, mods.split(','), 'js')
content,timestamp = concat_files(req.config.addons_path, files)
# TODO request set the Date of last modif and Etag
def js(self, req, mods=None):
files = [f[0] for f in self.manifest_glob(req, mods, 'js')]
content,timestamp = concat_files(files)
# TODO use timestamp to set Last mofified date and E-tag
return req.make_response(content, [('Content-Type', 'application/javascript')])
@openerpweb.httprequest
def home(self, req, s_action=None, **kw):
# script tags
jslist = ['/web/webclient/js']
if req.debug:
jslist = [i + '?debug=' + str(time.time()) for i in manifest_glob(req.config.addons_path, ['web'], 'js')]
js = "\n ".join(['<script type="text/javascript" src="%s"></script>'%i for i in jslist])
js = "\n ".join('<script type="text/javascript" src="%s"></script>'%i for i in self.manifest_list(req, None, 'js'))
css = "\n ".join('<link rel="stylesheet" href="%s">'%i for i in self.manifest_list(req, None, 'css'))
# css tags
csslist = ['/web/webclient/css']
if req.debug:
csslist = [i + '?debug=' + str(time.time()) for i in manifest_glob(req.config.addons_path, ['web'], 'css')]
css = "\n ".join(['<link rel="stylesheet" href="%s">'%i for i in csslist])
r = home_template % {
'javascript': js,
'css': css
r = html_template % {
'js': js,
'css': css,
'modules': simplejson.dumps(self.server_wide_modules(req)),
'init': 'new s.web.WebClient("oe").start();',
}
return r
@ -166,25 +134,26 @@ class WebClient(openerpweb.Controller):
"grouping", "decimal_point", "thousands_sep"])
else:
lang_obj = None
if lang.count("_") > 0:
separator = "_"
else:
separator = "@"
langs = lang.split(separator)
langs = [separator.join(langs[:x]) for x in range(1, len(langs) + 1)]
transs = {}
for addon_name in mods:
transl = {"messages":[]}
transs[addon_name] = transl
for l in langs:
f_name = os.path.join(req.config.addons_path, addon_name, "po", l + ".po")
addons_path = openerpweb.addons_manifest[addon_name]['addons_path']
f_name = os.path.join(addons_path, addon_name, "po", l + ".po")
if not os.path.exists(f_name):
continue
try:
with open(f_name) as t_file:
po = read_po(t_file)
po = babel.messages.pofile.read_po(t_file)
except:
continue
for x in po:
@ -240,7 +209,7 @@ class Database(openerpweb.Controller):
password, db = operator.itemgetter(
'drop_pwd', 'drop_db')(
dict(map(operator.itemgetter('name', 'value'), fields)))
try:
return req.session.proxy("db").drop(password, db)
except xmlrpclib.Fault, e:
@ -299,6 +268,7 @@ class Session(openerpweb.Controller):
"context": ctx,
"db": req.session._db
}
@openerpweb.jsonrequest
def get_session_info(self, req):
req.session.assert_valid(force=True)
@ -307,6 +277,7 @@ class Session(openerpweb.Controller):
"context": req.session.get_context() if req.session._uid else False,
"db": req.session._db
}
@openerpweb.jsonrequest
def change_password (self,req,fields):
old_password, new_password,confirm_password = operator.itemgetter('old_pwd', 'new_password','confirm_pwd')(
@ -322,6 +293,7 @@ class Session(openerpweb.Controller):
except:
return {'error': 'Original password incorrect, your password was not changed.', 'title': 'Change Password'}
return {'error': 'Error, password not changed !', 'title': 'Change Password'}
@openerpweb.jsonrequest
def sc_list(self, req):
return req.session.model('ir.ui.view_sc').get_sc(
@ -336,15 +308,25 @@ class Session(openerpweb.Controller):
}
except Exception, e:
return {"error": e, "title": "Languages"}
@openerpweb.jsonrequest
def modules(self, req):
# TODO query server for installed web modules
mods = []
for name, manifest in openerpweb.addons_manifest.items():
if name != 'web' and manifest.get('active', True):
mods.append(name)
return mods
# Compute available candidates module
loadable = openerpweb.addons_manifest.iterkeys()
loaded = req.config.server_wide_modules
candidates = [mod for mod in loadable if mod not in loaded]
# Compute active true modules that might be on the web side only
active = set(name for name in candidates
if openerpweb.addons_manifest[name].get('active'))
# Retrieve database installed modules
Modules = req.session.model('ir.module.module')
installed = set(module['name'] for module in Modules.search_read(
[('state','=','installed'), ('name','in', candidates)], ['name']))
# Merge both
return list(active | installed)
@openerpweb.jsonrequest
def eval_domain_and_context(self, req, contexts, domains,
@ -379,8 +361,8 @@ class Session(openerpweb.Controller):
no group by should be performed)
"""
context, domain = eval_context_and_domain(req.session,
openerpweb.nonliterals.CompoundContext(*(contexts or [])),
openerpweb.nonliterals.CompoundDomain(*(domains or [])))
web.common.nonliterals.CompoundContext(*(contexts or [])),
web.common.nonliterals.CompoundDomain(*(domains or [])))
group_by_sequence = []
for candidate in (group_by_seq or []):
@ -459,18 +441,27 @@ def load_actions_from_ir_values(req, key, key2, models, meta):
return [(id, name, clean_action(req, action))
for id, name, action in actions]
def clean_action(req, action):
def clean_action(req, action, do_not_eval=False):
action.setdefault('flags', {})
context = req.session.eval_context(req.context)
eval_ctx = req.session.evaluation_context(context)
# values come from the server, we can just eval them
if isinstance(action.get('context'), basestring):
action['context'] = eval( action['context'], eval_ctx ) or {}
if not do_not_eval:
# values come from the server, we can just eval them
if isinstance(action.get('context'), basestring):
action['context'] = eval( action['context'], eval_ctx ) or {}
if isinstance(action.get('domain'), basestring):
action['domain'] = eval( action['domain'], eval_ctx ) or []
else:
if 'context' in action:
action['context'] = parse_context(action['context'], req.session)
if 'domain' in action:
action['domain'] = parse_domain(action['domain'], req.session)
if isinstance(action.get('domain'), basestring):
action['domain'] = eval( action['domain'], eval_ctx ) or []
if 'type' not in action:
action['type'] = 'ir.actions.act_window_close'
if action['type'] == 'ir.actions.act_window':
return fix_view_modes(action)
@ -535,7 +526,7 @@ def fix_view_modes(action):
if 'views' not in action:
generate_views(action)
if action.pop('view_type') != 'form':
if action.pop('view_type', 'form') != 'form':
return action
action['views'] = [
@ -715,7 +706,7 @@ class DataSet(openerpweb.Controller):
args[domain_id] = d
if context_id and len(args) - 1 >= context_id:
args[context_id] = c
for i in xrange(len(args)):
if isinstance(args[i], web.common.nonliterals.BaseContext):
args[i] = req.session.eval_context(args[i])
@ -794,16 +785,16 @@ class View(openerpweb.Controller):
xml = self.transform_view(arch, session, evaluation_context)
else:
xml = ElementTree.fromstring(arch)
fvg['arch'] = Xml2Json.convert_element(xml)
fvg['arch'] = web.common.xml2json.Xml2Json.convert_element(xml)
for field in fvg['fields'].itervalues():
if field.get('views'):
for view in field["views"].itervalues():
self.process_view(session, view, None, transform)
if field.get('domain'):
field["domain"] = self.parse_domain(field["domain"], session)
field["domain"] = parse_domain(field["domain"], session)
if field.get('context'):
field["context"] = self.parse_context(field["context"], session)
field["context"] = parse_context(field["context"], session)
def process_toolbar(self, req, toolbar):
"""
@ -815,10 +806,10 @@ class View(openerpweb.Controller):
for actions in toolbar.itervalues():
for action in actions:
if 'context' in action:
action['context'] = self.parse_context(
action['context'] = parse_context(
action['context'], req.session)
if 'domain' in action:
action['domain'] = self.parse_domain(
action['domain'] = parse_domain(
action['domain'], req.session)
@openerpweb.jsonrequest
@ -857,39 +848,6 @@ class View(openerpweb.Controller):
self.parse_domains_and_contexts(elem, session)
return root
def parse_domain(self, domain, session):
""" Parses an arbitrary string containing a domain, transforms it
to either a literal domain or a :class:`openerpweb.nonliterals.Domain`
:param domain: the domain to parse, if the domain is not a string it
is assumed to be a literal domain and is returned as-is
:param session: Current OpenERP session
:type session: openerpweb.openerpweb.OpenERPSession
"""
if not isinstance(domain, (str, unicode)):
return domain
try:
return openerpweb.ast.literal_eval(domain)
except ValueError:
# not a literal
return openerpweb.nonliterals.Domain(session, domain)
def parse_context(self, context, session):
""" Parses an arbitrary string containing a context, transforms it
to either a literal context or a :class:`openerpweb.nonliterals.Context`
:param context: the context to parse, if the context is not a string it
is assumed to be a literal domain and is returned as-is
:param session: Current OpenERP session
:type session: openerpweb.openerpweb.OpenERPSession
"""
if not isinstance(context, (str, unicode)):
return context
try:
return openerpweb.ast.literal_eval(context)
except ValueError:
return openerpweb.nonliterals.Context(session, context)
def parse_domains_and_contexts(self, elem, session):
""" Converts domains and contexts from the view into Python objects,
either literals if they can be parsed by literal_eval or a special
@ -904,16 +862,49 @@ class View(openerpweb.Controller):
for el in ['domain', 'filter_domain']:
domain = elem.get(el, '').strip()
if domain:
elem.set(el, self.parse_domain(domain, session))
elem.set(el, parse_domain(domain, session))
for el in ['context', 'default_get']:
context_string = elem.get(el, '').strip()
if context_string:
elem.set(el, self.parse_context(context_string, session))
elem.set(el, parse_context(context_string, session))
@openerpweb.jsonrequest
def load(self, req, model, view_id, view_type, toolbar=False):
return self.fields_view_get(req, model, view_id, view_type, toolbar=toolbar)
def parse_domain(domain, session):
""" Parses an arbitrary string containing a domain, transforms it
to either a literal domain or a :class:`web.common.nonliterals.Domain`
:param domain: the domain to parse, if the domain is not a string it
is assumed to be a literal domain and is returned as-is
:param session: Current OpenERP session
:type session: openerpweb.openerpweb.OpenERPSession
"""
if not isinstance(domain, (str, unicode)):
return domain
try:
return ast.literal_eval(domain)
except ValueError:
# not a literal
return web.common.nonliterals.Domain(session, domain)
def parse_context(context, session):
""" Parses an arbitrary string containing a context, transforms it
to either a literal context or a :class:`web.common.nonliterals.Context`
:param context: the context to parse, if the context is not a string it
is assumed to be a literal domain and is returned as-is
:param session: Current OpenERP session
:type session: openerpweb.openerpweb.OpenERPSession
"""
if not isinstance(context, (str, unicode)):
return context
try:
return ast.literal_eval(context)
except ValueError:
return web.common.nonliterals.Context(session, context)
class ListView(View):
_cp_path = "/web/listview"
@ -959,27 +950,27 @@ class SearchView(View):
for field in fields.values():
# shouldn't convert the views too?
if field.get('domain'):
field["domain"] = self.parse_domain(field["domain"], req.session)
field["domain"] = parse_domain(field["domain"], req.session)
if field.get('context'):
field["context"] = self.parse_domain(field["context"], req.session)
field["context"] = parse_context(field["context"], req.session)
return {'fields': fields}
@openerpweb.jsonrequest
def get_filters(self, req, model):
Model = req.session.model("ir.filters")
filters = Model.get_filters(model)
for filter in filters:
filter["context"] = req.session.eval_context(self.parse_context(filter["context"], req.session))
filter["domain"] = req.session.eval_domain(self.parse_domain(filter["domain"], req.session))
filter["context"] = req.session.eval_context(parse_context(filter["context"], req.session))
filter["domain"] = req.session.eval_domain(parse_domain(filter["domain"], req.session))
return filters
@openerpweb.jsonrequest
def save_filter(self, req, model, name, context_to_save, domain):
Model = req.session.model("ir.filters")
ctx = openerpweb.nonliterals.CompoundContext(context_to_save)
ctx = web.common.nonliterals.CompoundContext(context_to_save)
ctx.session = req.session
ctx = ctx.evaluate()
domain = openerpweb.nonliterals.CompoundDomain(domain)
domain = web.common.nonliterals.CompoundDomain(domain)
domain.session = req.session
domain = domain.evaluate()
uid = req.session._uid
@ -1002,23 +993,27 @@ class Binary(openerpweb.Controller):
try:
if not id:
res = Model.default_get([field], context).get(field, '')
res = Model.default_get([field], context).get(field)
else:
res = Model.read([int(id)], [field], context)[0].get(field, '')
res = Model.read([int(id)], [field], context)[0].get(field)
image_data = base64.b64decode(res)
except (TypeError, xmlrpclib.Fault):
image_data = self.placeholder(req)
return req.make_response(image_data, [
('Content-Type', 'image/png'), ('Content-Length', len(image_data))])
def placeholder(self, req):
return open(os.path.join(req.addons_path, 'web', 'static', 'src', 'img', 'placeholder.png'), 'rb').read()
addons_path = openerpweb.addons_manifest['web']['addons_path']
return open(os.path.join(addons_path, 'web', 'static', 'src', 'img', 'placeholder.png'), 'rb').read()
@openerpweb.httprequest
def saveas(self, req, model, id, field, fieldname, **kw):
Model = req.session.model(model)
context = req.session.eval_context(req.context)
res = Model.read([int(id)], [field, fieldname], context)[0]
filecontent = res.get(field, '')
if id:
res = Model.read([int(id)], [field, fieldname], context)[0]
else:
res = Model.default_get([field, fieldname], context)
filecontent = base64.b64decode(res.get(field, ''))
if not filecontent:
return req.not_found()
else:
@ -1082,7 +1077,7 @@ class Action(openerpweb.Controller):
_cp_path = "/web/action"
@openerpweb.jsonrequest
def load(self, req, action_id):
def load(self, req, action_id, do_not_eval=False):
Actions = req.session.model('ir.actions.actions')
value = False
context = req.session.eval_context(req.context)
@ -1094,7 +1089,7 @@ class Action(openerpweb.Controller):
ctx.update(context)
action = req.session.model(action_type[0]['type']).read([action_id], False, ctx)
if action:
value = clean_action(req, action[0])
value = clean_action(req, action[0], do_not_eval)
return {'result': value}
@openerpweb.jsonrequest
@ -1370,7 +1365,7 @@ class Reports(View):
report_srv = req.session.proxy("report")
context = req.session.eval_context(
openerpweb.nonliterals.CompoundContext(
web.common.nonliterals.CompoundContext(
req.context or {}, action[ "context"]))
report_data = {}
@ -1378,11 +1373,10 @@ class Reports(View):
if 'report_type' in action:
report_data['report_type'] = action['report_type']
if 'datas' in action:
if 'form' in action['datas']:
report_data['form'] = action['datas']['form']
if 'ids' in action['datas']:
report_ids = action['datas']['ids']
report_ids = action['datas'].pop('ids')
report_data.update(action['datas'])
report_id = report_srv.report(
req.session._db, req.session._uid, req.session._password,
action["report_name"], report_ids,
@ -1394,6 +1388,7 @@ class Reports(View):
req.session._db, req.session._uid, req.session._password, report_id)
if report_struct["state"]:
break
time.sleep(self.POLLING_DELAY)
report = base64.b64decode(report_struct['result'])
@ -1407,3 +1402,107 @@ class Reports(View):
('Content-Type', report_mimetype),
('Content-Length', len(report))],
cookies={'fileToken': int(token)})
class Import(View):
_cp_path = "/web/import"
def fields_get(self, req, model):
Model = req.session.model(model)
fields = Model.fields_get(False, req.session.eval_context(req.context))
return fields
@openerpweb.httprequest
def detect_data(self, req, csvfile, csvsep, csvdel, csvcode, jsonp):
try:
data = list(csv.reader(
csvfile, quotechar=str(csvdel), delimiter=str(csvsep)))
except csv.Error, e:
csvfile.seek(0)
return '<script>window.top.%s(%s);</script>' % (
jsonp, simplejson.dumps({'error': {
'message': 'Error parsing CSV file: %s' % e,
# decodes each byte to a unicode character, which may or
# may not be printable, but decoding will succeed.
# Otherwise simplejson will try to decode the `str` using
# utf-8, which is very likely to blow up on characters out
# of the ascii range (in range [128, 256))
'preview': csvfile.read(200).decode('iso-8859-1')}}))
try:
return '<script>window.top.%s(%s);</script>' % (
jsonp, simplejson.dumps(
{'records': data[:10]}, encoding=csvcode))
except UnicodeDecodeError:
return '<script>window.top.%s(%s);</script>' % (
jsonp, simplejson.dumps({
'message': u"Failed to decode CSV file using encoding %s, "
u"try switching to a different encoding" % csvcode
}))
@openerpweb.httprequest
def import_data(self, req, model, csvfile, csvsep, csvdel, csvcode, jsonp,
meta):
modle_obj = req.session.model(model)
skip, indices, fields = operator.itemgetter('skip', 'indices', 'fields')(
simplejson.loads(meta))
error = None
if not (csvdel and len(csvdel) == 1):
error = u"The CSV delimiter must be a single character"
if not indices and fields:
error = u"You must select at least one field to import"
if error:
return '<script>window.top.%s(%s);</script>' % (
jsonp, simplejson.dumps({'error': {'message': error}}))
# skip ignored records
data_record = itertools.islice(
csv.reader(csvfile, quotechar=str(csvdel), delimiter=str(csvsep)),
skip, None)
# if only one index, itemgetter will return an atom rather than a tuple
if len(indices) == 1: mapper = lambda row: [row[indices[0]]]
else: mapper = operator.itemgetter(*indices)
data = None
error = None
try:
# decode each data row
data = [
[record.decode(csvcode) for record in row]
for row in itertools.imap(mapper, data_record)
# don't insert completely empty rows (can happen due to fields
# filtering in case of e.g. o2m content rows)
if any(row)
]
except UnicodeDecodeError:
error = u"Failed to decode CSV file using encoding %s" % csvcode
except csv.Error, e:
error = u"Could not process CSV file: %s" % e
# If the file contains nothing,
if not data:
error = u"File to import is empty"
if error:
return '<script>window.top.%s(%s);</script>' % (
jsonp, simplejson.dumps({'error': {'message': error}}))
try:
(code, record, message, _nope) = modle_obj.import_data(
fields, data, 'init', '', False,
req.session.eval_context(req.context))
except xmlrpclib.Fault, e:
error = {"message": u"%s, %s" % (e.faultCode, e.faultString)}
return '<script>window.top.%s(%s);</script>' % (
jsonp, simplejson.dumps({'error':error}))
if code != -1:
return '<script>window.top.%s(%s);</script>' % (
jsonp, simplejson.dumps({'success':True}))
msg = u"Error during import: %s\n\nTrying to import record %r" % (
message, record)
return '<script>window.top.%s(%s);</script>' % (
jsonp, simplejson.dumps({'error': {'message':msg}}))

707
addons/web/po/da.po Normal file
View File

@ -0,0 +1,707 @@
# Danish translation for openerp-web
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openerp-web package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-10-07 10:38+0200\n"
"PO-Revision-Date: 2011-10-11 14:21+0000\n"
"Last-Translator: Jonas Mortensen <Unknown>\n"
"Language-Team: Danish <da@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-10-12 04:44+0000\n"
"X-Generator: Launchpad (build 14124)\n"
#: addons/web/static/src/js/view_form.js:355
msgid ""
"Warning, the record has been modified, your changes will be discarded."
msgstr ""
"Advarsel, registreringen er blevet ændret, dine ændringer vil derfor blive "
"kasseret."
#: addons/web/static/src/js/view_form.js:1659
msgid "<em>   Search More...</em>"
msgstr "<em>   Søg efter mere....</em>"
#: addons/web/static/src/js/view_form.js:1672
#, python-format
msgid "<em>   Create \"<strong>%s</strong>\"</em>"
msgstr "<em>   Create \"<strong>%s</strong>\"</em>"
#: addons/web/static/src/js/view_form.js:1678
msgid "<em>   Create and Edit...</em>"
msgstr "<em>   Opret og rediger...</em>"
#: addons/web/static/src/js/views.js:568
msgid "You must choose at least one record."
msgstr "Du skal vælge mindst en registrering."
#: addons/web/static/src/js/views.js:569
msgid "Warning"
msgstr "Advarsel"
#: addons/web/static/src/js/views.js:609
msgid "Translations"
msgstr "Oversættelser"
#: addons/web/static/src/js/views.js:614 addons/web/static/src/xml/base.xml:0
msgid "Save"
msgstr "Gem"
#: addons/web/static/src/js/views.js:615
msgid "Close"
msgstr "Luk"
#: addons/web/static/src/xml/base.xml:0
msgid "x"
msgstr "x"
#: addons/web/static/src/xml/base.xml:0
msgid "#{title}"
msgstr "#(titel)"
#: addons/web/static/src/xml/base.xml:0
msgid "#{text}"
msgstr "#(tekst)"
#: addons/web/static/src/xml/base.xml:0
msgid "Powered by"
msgstr "Drevet af"
#: addons/web/static/src/xml/base.xml:0
msgid "openerp.com"
msgstr "openerp.com"
#: addons/web/static/src/xml/base.xml:0
msgid "."
msgstr ","
#: addons/web/static/src/xml/base.xml:0
msgid "Loading..."
msgstr "Indlæser..."
#: addons/web/static/src/xml/base.xml:0
msgid "Create"
msgstr "Opret"
#: addons/web/static/src/xml/base.xml:0
msgid "Drop"
msgstr "Drop"
#: addons/web/static/src/xml/base.xml:0
msgid "Backup"
msgstr "Sikkerhedskopi"
#: addons/web/static/src/xml/base.xml:0
msgid "Restore"
msgstr "Gendan"
#: addons/web/static/src/xml/base.xml:0
msgid "Password"
msgstr "Adgangskode"
#: addons/web/static/src/xml/base.xml:0
msgid "Back to Login"
msgstr "Tilbage til log ind"
#: addons/web/static/src/xml/base.xml:0
msgid "CREATE DATABASE"
msgstr "OPRET DATABASE"
#: addons/web/static/src/xml/base.xml:0
msgid "Master password:"
msgstr "Hovedadgangskode"
#: addons/web/static/src/xml/base.xml:0
msgid "New database name:"
msgstr "Nyt database navn:"
#: addons/web/static/src/xml/base.xml:0
msgid "Load Demonstration data:"
msgstr "Indlæs demonstrations data:"
#: addons/web/static/src/xml/base.xml:0
msgid "Default language:"
msgstr "Standardsprog:"
#: addons/web/static/src/xml/base.xml:0
msgid "Admin password:"
msgstr "Administrators adgangskode:"
#: addons/web/static/src/xml/base.xml:0
msgid "Confirm password:"
msgstr "Bekræft adgangskode:"
#: addons/web/static/src/xml/base.xml:0
msgid "DROP DATABASE"
msgstr "SLET DATABASE"
#: addons/web/static/src/xml/base.xml:0
msgid "Database:"
msgstr "Database:"
#: addons/web/static/src/xml/base.xml:0
msgid "Master Password:"
msgstr "Hovedadgangskode"
#: addons/web/static/src/xml/base.xml:0
msgid "BACKUP DATABASE"
msgstr "SIKKERHEDSKOPIER DATABASE"
#: addons/web/static/src/xml/base.xml:0
msgid "RESTORE DATABASE"
msgstr "GENDAN DATABASE"
#: addons/web/static/src/xml/base.xml:0
msgid "File:"
msgstr "Fil:"
#: addons/web/static/src/xml/base.xml:0
msgid "CHANGE MASTER PASSWORD"
msgstr "Skift hovedadgangskode"
#: addons/web/static/src/xml/base.xml:0
msgid "New master password:"
msgstr "Ny hovedadgangskode"
#: addons/web/static/src/xml/base.xml:0
msgid "Confirm new master password:"
msgstr "Bekræft ny hovedadgangskode"
#: addons/web/static/src/xml/base.xml:0
msgid "User:"
msgstr "Bruger:"
#: addons/web/static/src/xml/base.xml:0
msgid "Password:"
msgstr "Adgangskode:"
#: addons/web/static/src/xml/base.xml:0
msgid "Database"
msgstr "Database"
#: addons/web/static/src/xml/base.xml:0
msgid "Login"
msgstr "Log ind"
#: addons/web/static/src/xml/base.xml:0
msgid "Bad username or password"
msgstr "Forkert brugernavn eller adgangskode"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"We think that daily job activities can be more intuitive, efficient, "
"automated, .. and even fun."
msgstr ""
"Vi tror at daglige arbejdsaktiviteter kan blive mere intuitive, effektive og "
"automatiserede, .. and even fun."
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP's vision to be:"
msgstr "OpenERP´s vision at være:"
#: addons/web/static/src/xml/base.xml:0
msgid "Full featured"
msgstr "Fuldt udbygget"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"Today's enterprise challenges are multiple. We provide one module for each "
"need."
msgstr ""
"Udfordringer det stilles til nutidens virksomheder er blevet store. Vi "
"leverer moduler til et hvert behov."
#: addons/web/static/src/xml/base.xml:0
msgid "Open Source"
msgstr "Open source"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"To Build a great product, we rely on the knowledge of thousands of "
"contributors."
msgstr ""
"For at bygge et godt produkt, stoler vi på viden fra tusindevis af "
"bidragydere."
#: addons/web/static/src/xml/base.xml:0
msgid "User Friendly"
msgstr "Brugervenlig"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"In order to be productive, people need clean and easy to use interface."
msgstr "For at være produktiv kræves et nemt og brugervenligt interface."
#: addons/web/static/src/xml/base.xml:0
msgid "("
msgstr "("
#: addons/web/static/src/xml/base.xml:0
msgid ")"
msgstr ")"
#: addons/web/static/src/xml/base.xml:0
msgid "LOGOUT"
msgstr "LOG UD"
#: addons/web/static/src/xml/base.xml:0
msgid "&laquo;"
msgstr "&laquo;"
#: addons/web/static/src/xml/base.xml:0
msgid "&raquo;"
msgstr "&raquo;"
#: addons/web/static/src/xml/base.xml:0
msgid "oe_secondary_menu_item"
msgstr "oe_secondary_menu_item"
#: addons/web/static/src/xml/base.xml:0
msgid "oe_secondary_submenu_item"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Hide this tip"
msgstr "Skjul dette tip"
#: addons/web/static/src/xml/base.xml:0
msgid "Disable all tips"
msgstr "Deaktiver alle tips"
#: addons/web/static/src/xml/base.xml:0
msgid "View#"
msgstr "View#"
#: addons/web/static/src/xml/base.xml:0
msgid "Fields"
msgstr "Felter"
#: addons/web/static/src/xml/base.xml:0
msgid "View labels"
msgstr "Vis etiketter"
#: addons/web/static/src/xml/base.xml:0
msgid "Sidebar Relates"
msgstr "Relaterede til Sidebare"
#: addons/web/static/src/xml/base.xml:0
msgid "Field"
msgstr "Felt"
#: addons/web/static/src/xml/base.xml:0
msgid ":"
msgstr ":"
#: addons/web/static/src/xml/base.xml:0
msgid "Translate view"
msgstr "Se oversættelse"
#: addons/web/static/src/xml/base.xml:0
msgid "Translate sidebar"
msgstr "Oversæt sidebar"
#: addons/web/static/src/xml/base.xml:0
msgid "Delete"
msgstr "Slet"
#: addons/web/static/src/xml/base.xml:0
msgid "First"
msgstr "Første"
#: addons/web/static/src/xml/base.xml:0
msgid "<"
msgstr "<"
#: addons/web/static/src/xml/base.xml:0
msgid ">"
msgstr ">"
#: addons/web/static/src/xml/base.xml:0
msgid "Last"
msgstr "Sidste"
#: addons/web/static/src/xml/base.xml:0
msgid "♻"
msgstr "♻"
#: addons/web/static/src/xml/base.xml:0
msgid "Save & Edit"
msgstr "Gem & Rediger"
#: addons/web/static/src/xml/base.xml:0
msgid "Create & Edit"
msgstr "Opret & Rediger"
#: addons/web/static/src/xml/base.xml:0
msgid "New"
msgstr "Ny"
#: addons/web/static/src/xml/base.xml:0
msgid "Duplicate"
msgstr "Duplikér"
#: addons/web/static/src/xml/base.xml:0
msgid "Readonly/Editable"
msgstr "Skrivebeskyttet/redigerbar"
#: addons/web/static/src/xml/base.xml:0
msgid "<<"
msgstr "<<"
#: addons/web/static/src/xml/base.xml:0
msgid "0"
msgstr "0"
#: addons/web/static/src/xml/base.xml:0
msgid "/"
msgstr "/"
#: addons/web/static/src/xml/base.xml:0
msgid ">>"
msgstr ">>"
#: addons/web/static/src/xml/base.xml:0
msgid "Add"
msgstr "Tilføj"
#: addons/web/static/src/xml/base.xml:0
msgid "Unhandled widget"
msgstr "Ubehandlet widget"
#: addons/web/static/src/xml/base.xml:0
msgid "?"
msgstr "?"
#: addons/web/static/src/xml/base.xml:0
msgid "#"
msgstr "#"
#: addons/web/static/src/xml/base.xml:0
msgid "Done"
msgstr "Udført"
#: addons/web/static/src/xml/base.xml:0
msgid "Open..."
msgstr "Åbn..."
#: addons/web/static/src/xml/base.xml:0
msgid "Create..."
msgstr "Opret..."
#: addons/web/static/src/xml/base.xml:0
msgid "Search..."
msgstr "Søg..."
#: addons/web/static/src/xml/base.xml:0
msgid "..."
msgstr "..."
#: addons/web/static/src/xml/base.xml:0
msgid "Uploading ..."
msgstr "Uploader ..."
#: addons/web/static/src/xml/base.xml:0
msgid "Select"
msgstr "Markér"
#: addons/web/static/src/xml/base.xml:0
msgid "Save As"
msgstr "Gem Som"
#: addons/web/static/src/xml/base.xml:0
msgid "Clear"
msgstr "Ryd"
#: addons/web/static/src/xml/base.xml:0
msgid "Advanced Filter"
msgstr "Avanceret filtrering"
#: addons/web/static/src/xml/base.xml:0
msgid "-- Filters --"
msgstr "-- Filtreringer --"
#: addons/web/static/src/xml/base.xml:0
msgid "-- Actions --"
msgstr "-- Handlinger --"
#: addons/web/static/src/xml/base.xml:0
msgid "Save Filter"
msgstr "Gem filter"
#: addons/web/static/src/xml/base.xml:0
msgid "Manage Filters"
msgstr "Administrer Filtre"
#: addons/web/static/src/xml/base.xml:0
msgid "Filter Name:"
msgstr "Filter Navn:"
#: addons/web/static/src/xml/base.xml:0
msgid "(Any existing filter with the same name will be replaced)"
msgstr "(Et hvert filter med samme navn vil blive overskrevet)"
#: addons/web/static/src/xml/base.xml:0
msgid "Any of the following conditions must match"
msgstr "Enhver af de følgende betingelser skal være opfyldt"
#: addons/web/static/src/xml/base.xml:0
msgid "All the following conditions must match"
msgstr "Alle de følgende betingelser skal være opfyldt"
#: addons/web/static/src/xml/base.xml:0
msgid "None of the following conditions must match"
msgstr "Ingen af de følgende betingelser skal være opfyldt"
#: addons/web/static/src/xml/base.xml:0
msgid "Add condition"
msgstr "Tilføj betingelse"
#: addons/web/static/src/xml/base.xml:0
msgid "and"
msgstr "og"
#: addons/web/static/src/xml/base.xml:0
msgid "Cancel"
msgstr "Annullér"
#: addons/web/static/src/xml/base.xml:0
msgid "Save & New"
msgstr "Gem & Ny"
#: addons/web/static/src/xml/base.xml:0
msgid "Save & Close"
msgstr "Gem & Luk"
#: addons/web/static/src/xml/base.xml:0
msgid "Export"
msgstr "Eksportér"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"This wizard will export all data that matches the current search criteria to "
"a CSV file.\n"
" You can export all data or only the fields that can be "
"reimported after modification."
msgstr ""
"Denne guide vil eksportere alle de data der passe på de nuværende "
"søgekriterier til en CSV file.\n"
" Du kan eksportere alle data eller kun de felter der kan "
"genimporteres efter ændring."
#: addons/web/static/src/xml/base.xml:0
msgid "Export Type:"
msgstr "Eksporteringstype:"
#: addons/web/static/src/xml/base.xml:0
msgid "Import Compatible Export"
msgstr "Importer Kompatibel Eksport"
#: addons/web/static/src/xml/base.xml:0
msgid "Export all Data"
msgstr "Eksporter alt Data"
#: addons/web/static/src/xml/base.xml:0
msgid "Export Formats"
msgstr "Eksporter formater"
#: addons/web/static/src/xml/base.xml:0
msgid "Available fields"
msgstr "Tilgængelige felter"
#: addons/web/static/src/xml/base.xml:0
msgid "Fields to export"
msgstr "Felter der kan eksporteres"
#: addons/web/static/src/xml/base.xml:0
msgid "Save fields list"
msgstr "Gem listen med felter"
#: addons/web/static/src/xml/base.xml:0
msgid "Remove"
msgstr "Fjern"
#: addons/web/static/src/xml/base.xml:0
msgid "Remove All"
msgstr "Fjern alle"
#: addons/web/static/src/xml/base.xml:0
msgid "Name"
msgstr "Navn"
#: addons/web/static/src/xml/base.xml:0
msgid "&nbsp;"
msgstr "&nbsp;"
#: addons/web/static/src/xml/base.xml:0
msgid "Save as:"
msgstr "Gem som:"
#: addons/web/static/src/xml/base.xml:0
msgid "Ok"
msgstr "Ok"
#: addons/web/static/src/xml/base.xml:0
msgid "Saved exports:"
msgstr "Gem eksporteringer"
#: addons/web/static/src/xml/base.xml:0
msgid "Old Password:"
msgstr "Gammel adgangskode:"
#: addons/web/static/src/xml/base.xml:0
msgid "New Password:"
msgstr "Ny adgangskode:"
#: addons/web/static/src/xml/base.xml:0
msgid "Confirm Password:"
msgstr "Bekræft adgangskode:"
#: addons/web/static/src/xml/base.xml:0
msgid "Import"
msgstr "Importér"
#: addons/web/static/src/xml/base.xml:0
msgid "1. Import a .CSV file"
msgstr "1. Importér en .CSV fil"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"Select a .CSV file to import. If you need a sample of file to import,\n"
" you should use the export tool with the \"Import Compatible\" option."
msgstr ""
"Vælg en .CSV fil som du vil importere. Hvis du har brug et udsnit af filen "
"som du importere,\n"
" skal du bruge eksporteringsværktøjet med valgmuligheden \"Import "
"kompatibilitet\"."
#: addons/web/static/src/xml/base.xml:0
msgid "CSV File:"
msgstr "CSV Fil:"
#: addons/web/static/src/xml/base.xml:0
msgid "2. Check your file format"
msgstr "2. Kontroller dit filformat"
#: addons/web/static/src/xml/base.xml:0
msgid "Import Options"
msgstr "Importeringsindstillinger"
#: addons/web/static/src/xml/base.xml:0
msgid "Does your file have titles?"
msgstr "Har din fil titler?"
#: addons/web/static/src/xml/base.xml:0
msgid "Separator:"
msgstr "Adskiller:"
#: addons/web/static/src/xml/base.xml:0
msgid "Delimiter:"
msgstr "Begrænsning"
#: addons/web/static/src/xml/base.xml:0
msgid "Encoding:"
msgstr "Kodning:"
#: addons/web/static/src/xml/base.xml:0
msgid "UTF-8"
msgstr "UTF-8"
#: addons/web/static/src/xml/base.xml:0
msgid "Latin 1"
msgstr "Latin 1"
#: addons/web/static/src/xml/base.xml:0
msgid "Lines to skip"
msgstr "Linier, der springes over"
#: addons/web/static/src/xml/base.xml:0
msgid "The import failed due to:"
msgstr "Importeringen fejlede som følge af:"
#: addons/web/static/src/xml/base.xml:0
msgid "Here is a preview of the file we could not import:"
msgstr "Her er et preview of af filen som vi ikke kunne importere:"
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP Web"
msgstr "OpenERP Web"
#: addons/web/static/src/xml/base.xml:0
msgid "Version"
msgstr "Udgave"
#: addons/web/static/src/xml/base.xml:0
msgid "Copyright © 2011-TODAY OpenERP SA. All Rights Reserved."
msgstr "Copyright © 2011-TODAY OpenERP SA. All Rights Reserved."
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP is a trademark of the"
msgstr "OpenERP er et varemærke af"
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP SA Company"
msgstr "OpenERP SA Company"
#: addons/web/static/src/xml/base.xml:0
msgid "Licenced under the terms of"
msgstr "Licenseret i henhold til"
#: addons/web/static/src/xml/base.xml:0
msgid "GNU Affero General Public License"
msgstr "GNU Affero General Public License"
#: addons/web/static/src/xml/base.xml:0
msgid "About OpenERP"
msgstr "Om OpenERP"
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP"
msgstr "OpenERP"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"is a free enterprise-scale software system that is designed to boost\n"
" productivity and profit through data integration. It connects, "
"improves and\n"
" manages business processes in areas such as sales, finance, "
"supply chain,\n"
" project management, production, services, CRM, etc..."
msgstr ""
"er et gratis enterprise-scale software system, der er designet til at øge \n"
" produktivitet og profit via dataintegration. Systemet forbinder, "
"forbedrer og \n"
" håndterer forretningsprocesser inden for områder som salg, "
"økonomi, forsyningskæder, \n"
" projektledelse, produktion, service, CRM, etc..."
#: addons/web/static/src/xml/base.xml:0
msgid ""
"The system is platform-independent, and can be installed on Windows, Mac OS "
"X,\n"
" and various Linux and other Unix-based distributions. Its "
"architecture enables\n"
" new functionality to be rapidly created, modifications to be "
"made to a\n"
" production system and migration to a new version to be "
"straightforward."
msgstr ""
"Systemet er uafhængigt af bestemte platforme, og kan installeres på Windows, "
"Mac OS X,\n"
" og forskellige Linux og andre Unix-baserede distributioner. "
"Systemets arkitektur gør det\n"
" lige til at lave nye funktionaliteter,modifikationer til et\n"
" produktionssystem og migrere til nye vrsioner."
#: addons/web/static/src/xml/base.xml:0
msgid ""
"Depending on your needs, OpenERP is available through a web or application "
"client."
msgstr ""
"Afhængig af dine behov, er OpenERP tilgængelig igennem en web- eller "
"applikationsklient."

708
addons/web/po/de.po Normal file
View File

@ -0,0 +1,708 @@
# German translation for openerp-web
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openerp-web package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-10-07 10:38+0200\n"
"PO-Revision-Date: 2011-10-10 20:59+0000\n"
"Last-Translator: Felix Schubert <Unknown>\n"
"Language-Team: German <de@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-10-11 05:42+0000\n"
"X-Generator: Launchpad (build 14123)\n"
#: addons/web/static/src/js/view_form.js:355
msgid ""
"Warning, the record has been modified, your changes will be discarded."
msgstr ""
"Achtung der Datensatz wurde bearbeitet, alle Änderungen werden verworfen!"
#: addons/web/static/src/js/view_form.js:1659
msgid "<em>   Search More...</em>"
msgstr "<em>   Suche mehr...</em>"
#: addons/web/static/src/js/view_form.js:1672
#, python-format
msgid "<em>   Create \"<strong>%s</strong>\"</em>"
msgstr "<em>   Anlegen \"<strong>%s</strong>\"</em>"
#: addons/web/static/src/js/view_form.js:1678
msgid "<em>   Create and Edit...</em>"
msgstr "<em>   Anlegen und Bearbeiten...</em>"
#: addons/web/static/src/js/views.js:568
msgid "You must choose at least one record."
msgstr "Sie müssen mindestens einen Datensatz auswählen"
#: addons/web/static/src/js/views.js:569
msgid "Warning"
msgstr "Warnung!"
#: addons/web/static/src/js/views.js:609
msgid "Translations"
msgstr "Übersetzungen"
#: addons/web/static/src/js/views.js:614 addons/web/static/src/xml/base.xml:0
msgid "Save"
msgstr "Speichern"
#: addons/web/static/src/js/views.js:615
msgid "Close"
msgstr "Schließen"
#: addons/web/static/src/xml/base.xml:0
msgid "x"
msgstr "x"
#: addons/web/static/src/xml/base.xml:0
msgid "#{title}"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "#{text}"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Powered by"
msgstr "unterstützt durch"
#: addons/web/static/src/xml/base.xml:0
msgid "openerp.com"
msgstr "openerp.com"
#: addons/web/static/src/xml/base.xml:0
msgid "."
msgstr "."
#: addons/web/static/src/xml/base.xml:0
msgid "Loading..."
msgstr "Lade..."
#: addons/web/static/src/xml/base.xml:0
msgid "Create"
msgstr "Erzeugen"
#: addons/web/static/src/xml/base.xml:0
msgid "Drop"
msgstr "Löschen"
#: addons/web/static/src/xml/base.xml:0
msgid "Backup"
msgstr "Sichern"
#: addons/web/static/src/xml/base.xml:0
msgid "Restore"
msgstr "Wiederherstellen"
#: addons/web/static/src/xml/base.xml:0
msgid "Password"
msgstr "Passwort"
#: addons/web/static/src/xml/base.xml:0
msgid "Back to Login"
msgstr "Zurück zur Anmeldung"
#: addons/web/static/src/xml/base.xml:0
msgid "CREATE DATABASE"
msgstr "Datenbank anlegen"
#: addons/web/static/src/xml/base.xml:0
msgid "Master password:"
msgstr "Master Passwort"
#: addons/web/static/src/xml/base.xml:0
msgid "New database name:"
msgstr "Name der neuen Datenbank:"
#: addons/web/static/src/xml/base.xml:0
msgid "Load Demonstration data:"
msgstr "Beispieldaten laden:"
#: addons/web/static/src/xml/base.xml:0
msgid "Default language:"
msgstr "Standardsprache:"
#: addons/web/static/src/xml/base.xml:0
msgid "Admin password:"
msgstr "Admin Passwort"
#: addons/web/static/src/xml/base.xml:0
msgid "Confirm password:"
msgstr "Passwort wiederholen:"
#: addons/web/static/src/xml/base.xml:0
msgid "DROP DATABASE"
msgstr "Datenbank löschen"
#: addons/web/static/src/xml/base.xml:0
msgid "Database:"
msgstr "Datenbank:"
#: addons/web/static/src/xml/base.xml:0
msgid "Master Password:"
msgstr "Master Passwort"
#: addons/web/static/src/xml/base.xml:0
msgid "BACKUP DATABASE"
msgstr "Datenbank sichern"
#: addons/web/static/src/xml/base.xml:0
msgid "RESTORE DATABASE"
msgstr "Datenbank wiederherstellen"
#: addons/web/static/src/xml/base.xml:0
msgid "File:"
msgstr "Datei:"
#: addons/web/static/src/xml/base.xml:0
msgid "CHANGE MASTER PASSWORD"
msgstr "Master Passwort ändern"
#: addons/web/static/src/xml/base.xml:0
msgid "New master password:"
msgstr "Neues Master Passwort:"
#: addons/web/static/src/xml/base.xml:0
msgid "Confirm new master password:"
msgstr "Bestätigen Sie das neue Master Passwort:"
#: addons/web/static/src/xml/base.xml:0
msgid "User:"
msgstr "Benutzer:"
#: addons/web/static/src/xml/base.xml:0
msgid "Password:"
msgstr "Passwort:"
#: addons/web/static/src/xml/base.xml:0
msgid "Database"
msgstr "Datenbank"
#: addons/web/static/src/xml/base.xml:0
msgid "Login"
msgstr "Anmeldung"
#: addons/web/static/src/xml/base.xml:0
msgid "Bad username or password"
msgstr "Falscher Benutzername oder Passwort"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"We think that daily job activities can be more intuitive, efficient, "
"automated, .. and even fun."
msgstr ""
"Wir sind der Überzeugung, das die tägliche Arbeit intuitiver, effizienter, "
"automatisierter und mit mehr Spaß verbunden sein kann."
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP's vision to be:"
msgstr "OpenERP's Vision ist:"
#: addons/web/static/src/xml/base.xml:0
msgid "Full featured"
msgstr "vollständiges"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"Today's enterprise challenges are multiple. We provide one module for each "
"need."
msgstr ""
"Die heutigen Unternehmensherausforderungen sind vielfältig. Wir bieten Ihnen "
"ein Modul für jede Anforderung."
#: addons/web/static/src/xml/base.xml:0
msgid "Open Source"
msgstr "Open Source"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"To Build a great product, we rely on the knowledge of thousands of "
"contributors."
msgstr ""
"Um ein grossartiges Produkt bereitzustellen, vertrauen wir auf das Wissen "
"von Tausenden von Unterstützern"
#: addons/web/static/src/xml/base.xml:0
msgid "User Friendly"
msgstr "Benutzerfreundlich"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"In order to be productive, people need clean and easy to use interface."
msgstr ""
"Um produktiv arbeiten zu können, benötigen die Mitarbeiter eine einfache und "
"klar strukturierte Oberfläche."
#: addons/web/static/src/xml/base.xml:0
msgid "("
msgstr "("
#: addons/web/static/src/xml/base.xml:0
msgid ")"
msgstr ")"
#: addons/web/static/src/xml/base.xml:0
msgid "LOGOUT"
msgstr "Abmeldung"
#: addons/web/static/src/xml/base.xml:0
msgid "&laquo;"
msgstr "&laquo;"
#: addons/web/static/src/xml/base.xml:0
msgid "&raquo;"
msgstr "&raquo;"
#: addons/web/static/src/xml/base.xml:0
msgid "oe_secondary_menu_item"
msgstr "oe_secondary_menu_item"
#: addons/web/static/src/xml/base.xml:0
msgid "oe_secondary_submenu_item"
msgstr "oe_secondary_submenu_item"
#: addons/web/static/src/xml/base.xml:0
msgid "Hide this tip"
msgstr "Tip verbergen"
#: addons/web/static/src/xml/base.xml:0
msgid "Disable all tips"
msgstr "Deaktiviere alle Tipps"
#: addons/web/static/src/xml/base.xml:0
msgid "View#"
msgstr "Ansicht#"
#: addons/web/static/src/xml/base.xml:0
msgid "Fields"
msgstr "Felder"
#: addons/web/static/src/xml/base.xml:0
msgid "View labels"
msgstr "Feldbeschreibung anzeigen"
#: addons/web/static/src/xml/base.xml:0
msgid "Sidebar Relates"
msgstr "Seitenleiste bezieht sich auf"
#: addons/web/static/src/xml/base.xml:0
msgid "Field"
msgstr "Feld"
#: addons/web/static/src/xml/base.xml:0
msgid ":"
msgstr ":"
#: addons/web/static/src/xml/base.xml:0
msgid "Translate view"
msgstr "Übersetungsansicht"
#: addons/web/static/src/xml/base.xml:0
msgid "Translate sidebar"
msgstr "Seitenleiste übersetzen"
#: addons/web/static/src/xml/base.xml:0
msgid "Delete"
msgstr "Löschen"
#: addons/web/static/src/xml/base.xml:0
msgid "First"
msgstr "Erste"
#: addons/web/static/src/xml/base.xml:0
msgid "<"
msgstr "<"
#: addons/web/static/src/xml/base.xml:0
msgid ">"
msgstr ">"
#: addons/web/static/src/xml/base.xml:0
msgid "Last"
msgstr "Ende"
#: addons/web/static/src/xml/base.xml:0
msgid "♻"
msgstr "♻"
#: addons/web/static/src/xml/base.xml:0
msgid "Save & Edit"
msgstr "Sichern & Bearbeiten"
#: addons/web/static/src/xml/base.xml:0
msgid "Create & Edit"
msgstr "Anlegen & Bearbeiten"
#: addons/web/static/src/xml/base.xml:0
msgid "New"
msgstr "Neu"
#: addons/web/static/src/xml/base.xml:0
msgid "Duplicate"
msgstr "Kopieren"
#: addons/web/static/src/xml/base.xml:0
msgid "Readonly/Editable"
msgstr "Lesezugriff/Bearbeitbar"
#: addons/web/static/src/xml/base.xml:0
msgid "<<"
msgstr "<<"
#: addons/web/static/src/xml/base.xml:0
msgid "0"
msgstr "0"
#: addons/web/static/src/xml/base.xml:0
msgid "/"
msgstr "/"
#: addons/web/static/src/xml/base.xml:0
msgid ">>"
msgstr ">>"
#: addons/web/static/src/xml/base.xml:0
msgid "Add"
msgstr "Hinzufügen"
#: addons/web/static/src/xml/base.xml:0
msgid "Unhandled widget"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "?"
msgstr "?"
#: addons/web/static/src/xml/base.xml:0
msgid "#"
msgstr "Nr."
#: addons/web/static/src/xml/base.xml:0
msgid "Done"
msgstr "Abgeschlossen"
#: addons/web/static/src/xml/base.xml:0
msgid "Open..."
msgstr "Öffnen …"
#: addons/web/static/src/xml/base.xml:0
msgid "Create..."
msgstr "Erzeugen …"
#: addons/web/static/src/xml/base.xml:0
msgid "Search..."
msgstr "Suchen ..."
#: addons/web/static/src/xml/base.xml:0
msgid "..."
msgstr "…"
#: addons/web/static/src/xml/base.xml:0
msgid "Uploading ..."
msgstr "Hochladen ..."
#: addons/web/static/src/xml/base.xml:0
msgid "Select"
msgstr "Auswählen"
#: addons/web/static/src/xml/base.xml:0
msgid "Save As"
msgstr "Speichern unter"
#: addons/web/static/src/xml/base.xml:0
msgid "Clear"
msgstr "Leeren"
#: addons/web/static/src/xml/base.xml:0
msgid "Advanced Filter"
msgstr "Erweiterter Filter"
#: addons/web/static/src/xml/base.xml:0
msgid "-- Filters --"
msgstr "-- Filter --"
#: addons/web/static/src/xml/base.xml:0
msgid "-- Actions --"
msgstr "-- Aktionen --"
#: addons/web/static/src/xml/base.xml:0
msgid "Save Filter"
msgstr "Filter speichern"
#: addons/web/static/src/xml/base.xml:0
msgid "Manage Filters"
msgstr "Filter verwalten"
#: addons/web/static/src/xml/base.xml:0
msgid "Filter Name:"
msgstr "Filter Name:"
#: addons/web/static/src/xml/base.xml:0
msgid "(Any existing filter with the same name will be replaced)"
msgstr "(Jeder existierende Filter mit dem selben Namen wird ersetzt)"
#: addons/web/static/src/xml/base.xml:0
msgid "Any of the following conditions must match"
msgstr "Eine der folgenden Bedingungen muss zutreffen"
#: addons/web/static/src/xml/base.xml:0
msgid "All the following conditions must match"
msgstr "Alle der folgenden Bedingungen müssen zutreffen"
#: addons/web/static/src/xml/base.xml:0
msgid "None of the following conditions must match"
msgstr "Keine der folgenden Bedingungen müssen zutreffen"
#: addons/web/static/src/xml/base.xml:0
msgid "Add condition"
msgstr "Bedingung hinzufügen"
#: addons/web/static/src/xml/base.xml:0
msgid "and"
msgstr "und"
#: addons/web/static/src/xml/base.xml:0
msgid "Cancel"
msgstr "Abbrechen"
#: addons/web/static/src/xml/base.xml:0
msgid "Save & New"
msgstr "Speichern & Neu"
#: addons/web/static/src/xml/base.xml:0
msgid "Save & Close"
msgstr "Speichern & Beenden"
#: addons/web/static/src/xml/base.xml:0
msgid "Export"
msgstr "Export"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"This wizard will export all data that matches the current search criteria to "
"a CSV file.\n"
" You can export all data or only the fields that can be "
"reimported after modification."
msgstr ""
"Dieser Assistent wird alle Daten in eine CSV exportieren, die den aktuellen "
"Suchbedingungen entsprechen.\n"
" Sie können alle Daten oder nur die Felder exportieren, die nach einer "
"Bearbeitung wieder importiert werden können."
#: addons/web/static/src/xml/base.xml:0
msgid "Export Type:"
msgstr "Export Typ:"
#: addons/web/static/src/xml/base.xml:0
msgid "Import Compatible Export"
msgstr "Importiere kompatible Exportfelder"
#: addons/web/static/src/xml/base.xml:0
msgid "Export all Data"
msgstr "Alle Daten exportieren"
#: addons/web/static/src/xml/base.xml:0
msgid "Export Formats"
msgstr "Export Formate"
#: addons/web/static/src/xml/base.xml:0
msgid "Available fields"
msgstr "Verfügbare Felder"
#: addons/web/static/src/xml/base.xml:0
msgid "Fields to export"
msgstr "Zu exportierende Felder"
#: addons/web/static/src/xml/base.xml:0
msgid "Save fields list"
msgstr "Feldliste speichern"
#: addons/web/static/src/xml/base.xml:0
msgid "Remove"
msgstr "Löschen"
#: addons/web/static/src/xml/base.xml:0
msgid "Remove All"
msgstr "Alle löschen"
#: addons/web/static/src/xml/base.xml:0
msgid "Name"
msgstr "Name"
#: addons/web/static/src/xml/base.xml:0
msgid "&nbsp;"
msgstr "&nbsp;"
#: addons/web/static/src/xml/base.xml:0
msgid "Save as:"
msgstr "Speichern unter:"
#: addons/web/static/src/xml/base.xml:0
msgid "Ok"
msgstr "Ok"
#: addons/web/static/src/xml/base.xml:0
msgid "Saved exports:"
msgstr "Gespeicherte Exporte:"
#: addons/web/static/src/xml/base.xml:0
msgid "Old Password:"
msgstr "Altes Passwort:"
#: addons/web/static/src/xml/base.xml:0
msgid "New Password:"
msgstr "Neues Passwort:"
#: addons/web/static/src/xml/base.xml:0
msgid "Confirm Password:"
msgstr "Passwort bestätigen:"
#: addons/web/static/src/xml/base.xml:0
msgid "Import"
msgstr "Import"
#: addons/web/static/src/xml/base.xml:0
msgid "1. Import a .CSV file"
msgstr "1. Importiere eine .CSV Datei"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"Select a .CSV file to import. If you need a sample of file to import,\n"
" you should use the export tool with the \"Import Compatible\" option."
msgstr ""
"Wählen Sie eine CSV Datei aus, die Sie importieren möchten. Wenn Sie eine "
"Beispieldatei benötigen,\n"
" sollten Sie beim Export die Option \"Import-Kompatibel\" wählen."
#: addons/web/static/src/xml/base.xml:0
msgid "CSV File:"
msgstr "CSV Datei:"
#: addons/web/static/src/xml/base.xml:0
msgid "2. Check your file format"
msgstr "2. Überprüfen Sie das Dateiformat"
#: addons/web/static/src/xml/base.xml:0
msgid "Import Options"
msgstr "Import-Einstellungen"
#: addons/web/static/src/xml/base.xml:0
msgid "Does your file have titles?"
msgstr "Enthält Ihre Datei eine Titel Zeile?"
#: addons/web/static/src/xml/base.xml:0
msgid "Separator:"
msgstr "Trennzeichen:"
#: addons/web/static/src/xml/base.xml:0
msgid "Delimiter:"
msgstr "Feldtrenner:"
#: addons/web/static/src/xml/base.xml:0
msgid "Encoding:"
msgstr "Zeichenkodierung:"
#: addons/web/static/src/xml/base.xml:0
msgid "UTF-8"
msgstr "UTF-8"
#: addons/web/static/src/xml/base.xml:0
msgid "Latin 1"
msgstr "Latin 1"
#: addons/web/static/src/xml/base.xml:0
msgid "Lines to skip"
msgstr "Zu überspringende Zeilen"
#: addons/web/static/src/xml/base.xml:0
msgid "The import failed due to:"
msgstr "Der Import schlug fehl, da:"
#: addons/web/static/src/xml/base.xml:0
msgid "Here is a preview of the file we could not import:"
msgstr "Hier ist eine Vorschau der Datei die nicht importiert werden konnte"
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP Web"
msgstr "OpenERP Web"
#: addons/web/static/src/xml/base.xml:0
msgid "Version"
msgstr "Version"
#: addons/web/static/src/xml/base.xml:0
msgid "Copyright © 2011-TODAY OpenERP SA. All Rights Reserved."
msgstr "Copyright © 2011 OpenERP SA. Alle Rechte vorbehalten."
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP is a trademark of the"
msgstr "OpenERP ist eine Marke der"
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP SA Company"
msgstr "OpenERP SA"
#: addons/web/static/src/xml/base.xml:0
msgid "Licenced under the terms of"
msgstr "Lizensiert unter den Bedingungen der"
#: addons/web/static/src/xml/base.xml:0
msgid "GNU Affero General Public License"
msgstr "GNU Affero General Public License"
#: addons/web/static/src/xml/base.xml:0
msgid "About OpenERP"
msgstr "Über OpenERP"
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP"
msgstr "OpenERP"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"is a free enterprise-scale software system that is designed to boost\n"
" productivity and profit through data integration. It connects, "
"improves and\n"
" manages business processes in areas such as sales, finance, "
"supply chain,\n"
" project management, production, services, CRM, etc..."
msgstr ""
"ist eine freie und skalierbare Unternehmenssoftware, die folgende "
"Unternehmensprozesse beschleunigt\n"
"Produktivität und Umsatz aufgrund der integrierten Datenhaltung. Sie "
"verbindet, verbessert und\n"
"verwaltet Geschäftsprozesse in den Geschäftsfeldern Vertrieb, Finanzen, "
"Lieferketten,\n"
"Projektmanagement, Produktion, Produktunterstützung, CRM, usw..."
#: addons/web/static/src/xml/base.xml:0
msgid ""
"The system is platform-independent, and can be installed on Windows, Mac OS "
"X,\n"
" and various Linux and other Unix-based distributions. Its "
"architecture enables\n"
" new functionality to be rapidly created, modifications to be "
"made to a\n"
" production system and migration to a new version to be "
"straightforward."
msgstr ""
"Das System ist plattform-unabhängig und kann unter Windows, Mac OS X,\n"
"vielen Linux-Derivaten und anderen Unix-basierten Betriebssystem betrieben "
"werden. Seine Architektur ermöglicht\n"
"neue Funktionen schnell zu entwickeln, Anpassungen an einem produktiven "
"System vorzunehmen\n"
"und Migrationen auf neue Releases schnell umzusetzen."
#: addons/web/static/src/xml/base.xml:0
msgid ""
"Depending on your needs, OpenERP is available through a web or application "
"client."
msgstr ""
"Abhängig von Ihren Systemanforderungen, steht OpenERP entweder als "
"eigenständiger Client oder als webbasierte Anwendung zur Verfügung."

710
addons/web/po/es.po Normal file
View File

@ -0,0 +1,710 @@
# Spanish translation for openerp-web
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openerp-web package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-10-07 10:38+0200\n"
"PO-Revision-Date: 2011-10-19 07:27+0000\n"
"Last-Translator: Amós Oviedo <Unknown>\n"
"Language-Team: Spanish <es@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-10-20 04:48+0000\n"
"X-Generator: Launchpad (build 14165)\n"
#: addons/web/static/src/js/view_form.js:355
msgid ""
"Warning, the record has been modified, your changes will be discarded."
msgstr ""
"Advertencia, el registro se ha modificado, los cambios serán descartados."
#: addons/web/static/src/js/view_form.js:1659
msgid "<em>   Search More...</em>"
msgstr "<em>   Buscar más...</em>"
#: addons/web/static/src/js/view_form.js:1672
#, python-format
msgid "<em>   Create \"<strong>%s</strong>\"</em>"
msgstr "<em>   Crear \"<strong>%s</strong>\"</em>"
#: addons/web/static/src/js/view_form.js:1678
msgid "<em>   Create and Edit...</em>"
msgstr "<em>   Crear y Editar...</em>"
#: addons/web/static/src/js/views.js:568
msgid "You must choose at least one record."
msgstr "Debe seleccionar al menos un registro."
#: addons/web/static/src/js/views.js:569
msgid "Warning"
msgstr "Advertencia"
#: addons/web/static/src/js/views.js:609
msgid "Translations"
msgstr "Traducciones"
#: addons/web/static/src/js/views.js:614 addons/web/static/src/xml/base.xml:0
msgid "Save"
msgstr "Guardar"
#: addons/web/static/src/js/views.js:615
msgid "Close"
msgstr "Cerrar"
#: addons/web/static/src/xml/base.xml:0
msgid "x"
msgstr "x"
#: addons/web/static/src/xml/base.xml:0
msgid "#{title}"
msgstr "#{title}"
#: addons/web/static/src/xml/base.xml:0
msgid "#{text}"
msgstr "#{text}"
#: addons/web/static/src/xml/base.xml:0
msgid "Powered by"
msgstr "Desarrollado por"
#: addons/web/static/src/xml/base.xml:0
msgid "openerp.com"
msgstr "openerp.com"
#: addons/web/static/src/xml/base.xml:0
msgid "."
msgstr "."
#: addons/web/static/src/xml/base.xml:0
msgid "Loading..."
msgstr "Cargando…"
#: addons/web/static/src/xml/base.xml:0
msgid "Create"
msgstr "Crear"
#: addons/web/static/src/xml/base.xml:0
msgid "Drop"
msgstr "Eliminar"
#: addons/web/static/src/xml/base.xml:0
msgid "Backup"
msgstr "Copia de seguridad"
#: addons/web/static/src/xml/base.xml:0
msgid "Restore"
msgstr "Restaurar"
#: addons/web/static/src/xml/base.xml:0
msgid "Password"
msgstr "Contraseña"
#: addons/web/static/src/xml/base.xml:0
msgid "Back to Login"
msgstr "Volver al Inicio de sesión"
#: addons/web/static/src/xml/base.xml:0
msgid "CREATE DATABASE"
msgstr "CREAR BASE DE DATOS"
#: addons/web/static/src/xml/base.xml:0
msgid "Master password:"
msgstr "Contraseña maestra"
#: addons/web/static/src/xml/base.xml:0
msgid "New database name:"
msgstr "Nombre de la nueva base de datos:"
#: addons/web/static/src/xml/base.xml:0
msgid "Load Demonstration data:"
msgstr "Cargar datos de demostración:"
#: addons/web/static/src/xml/base.xml:0
msgid "Default language:"
msgstr "Idioma por defecto:"
#: addons/web/static/src/xml/base.xml:0
msgid "Admin password:"
msgstr "Contraseña de Admin:"
#: addons/web/static/src/xml/base.xml:0
msgid "Confirm password:"
msgstr "Confirmar contraseña:"
#: addons/web/static/src/xml/base.xml:0
msgid "DROP DATABASE"
msgstr "ELIMINAR BASE DE DATOS"
#: addons/web/static/src/xml/base.xml:0
msgid "Database:"
msgstr "Base de datos:"
#: addons/web/static/src/xml/base.xml:0
msgid "Master Password:"
msgstr "Contraseña Maestra"
#: addons/web/static/src/xml/base.xml:0
msgid "BACKUP DATABASE"
msgstr "COPIA DE SEGURIDAD DE LA BASE DE DATOS"
#: addons/web/static/src/xml/base.xml:0
msgid "RESTORE DATABASE"
msgstr "RESTAURAR BASE DE DATOS"
#: addons/web/static/src/xml/base.xml:0
msgid "File:"
msgstr "Archivo:"
#: addons/web/static/src/xml/base.xml:0
msgid "CHANGE MASTER PASSWORD"
msgstr "CAMBIAR CONTRASEÑA MAESTRA"
#: addons/web/static/src/xml/base.xml:0
msgid "New master password:"
msgstr "Nueva contraseña maestra:"
#: addons/web/static/src/xml/base.xml:0
msgid "Confirm new master password:"
msgstr "Confirmar nueva contraseña maestra:"
#: addons/web/static/src/xml/base.xml:0
msgid "User:"
msgstr "Usuario:"
#: addons/web/static/src/xml/base.xml:0
msgid "Password:"
msgstr "Contraseña:"
#: addons/web/static/src/xml/base.xml:0
msgid "Database"
msgstr "Database"
#: addons/web/static/src/xml/base.xml:0
msgid "Login"
msgstr "Inicio de sesión"
#: addons/web/static/src/xml/base.xml:0
msgid "Bad username or password"
msgstr "Nombre de usuario o contraseña incorrectos"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"We think that daily job activities can be more intuitive, efficient, "
"automated, .. and even fun."
msgstr ""
"Creemos que las actividades diarias de trabajo pueden ser más intuitivas, "
"eficientes y automatizadas, .. e incluso divertidas."
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP's vision to be:"
msgstr "Los objetivos de OpenERP son ser:"
#: addons/web/static/src/xml/base.xml:0
msgid "Full featured"
msgstr "Con todas las funciones"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"Today's enterprise challenges are multiple. We provide one module for each "
"need."
msgstr ""
"Los retos actuales de la empresa son múltiples. Ofrecemos un módulo para "
"cada necesidad."
#: addons/web/static/src/xml/base.xml:0
msgid "Open Source"
msgstr "Código abierto"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"To Build a great product, we rely on the knowledge of thousands of "
"contributors."
msgstr ""
"Para construir un gran producto, contamos con los conocimientos de miles de "
"contribuyentes."
#: addons/web/static/src/xml/base.xml:0
msgid "User Friendly"
msgstr "Fácil de usar"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"In order to be productive, people need clean and easy to use interface."
msgstr ""
"Con el fin de ser productivo, la gente necesita una interfaz clara y fácil "
"de usar."
#: addons/web/static/src/xml/base.xml:0
msgid "("
msgstr "("
#: addons/web/static/src/xml/base.xml:0
msgid ")"
msgstr ")"
#: addons/web/static/src/xml/base.xml:0
msgid "LOGOUT"
msgstr "CERRAR SESIÓN"
#: addons/web/static/src/xml/base.xml:0
msgid "&laquo;"
msgstr "&laquo;"
#: addons/web/static/src/xml/base.xml:0
msgid "&raquo;"
msgstr "&raquo;"
#: addons/web/static/src/xml/base.xml:0
msgid "oe_secondary_menu_item"
msgstr "oe_secondary_menu_item"
#: addons/web/static/src/xml/base.xml:0
msgid "oe_secondary_submenu_item"
msgstr "oe_secondary_submenu_item"
#: addons/web/static/src/xml/base.xml:0
msgid "Hide this tip"
msgstr "Ocultar esta sugerencia"
#: addons/web/static/src/xml/base.xml:0
msgid "Disable all tips"
msgstr "Desactivar todas las sugerencias"
#: addons/web/static/src/xml/base.xml:0
msgid "View#"
msgstr "Vista#"
#: addons/web/static/src/xml/base.xml:0
msgid "Fields"
msgstr "Campos"
#: addons/web/static/src/xml/base.xml:0
msgid "View labels"
msgstr "Ver etiquetas"
#: addons/web/static/src/xml/base.xml:0
msgid "Sidebar Relates"
msgstr "Se relaciona con la barra lateral"
#: addons/web/static/src/xml/base.xml:0
msgid "Field"
msgstr "Campo"
#: addons/web/static/src/xml/base.xml:0
msgid ":"
msgstr ":"
#: addons/web/static/src/xml/base.xml:0
msgid "Translate view"
msgstr "Traducir vista"
#: addons/web/static/src/xml/base.xml:0
msgid "Translate sidebar"
msgstr "Traducir barra lateral"
#: addons/web/static/src/xml/base.xml:0
msgid "Delete"
msgstr "Borrar"
#: addons/web/static/src/xml/base.xml:0
msgid "First"
msgstr "Primero"
#: addons/web/static/src/xml/base.xml:0
msgid "<"
msgstr "<"
#: addons/web/static/src/xml/base.xml:0
msgid ">"
msgstr ">"
#: addons/web/static/src/xml/base.xml:0
msgid "Last"
msgstr "Último"
#: addons/web/static/src/xml/base.xml:0
msgid "♻"
msgstr "♻"
#: addons/web/static/src/xml/base.xml:0
msgid "Save & Edit"
msgstr "Guardar y Editar"
#: addons/web/static/src/xml/base.xml:0
msgid "Create & Edit"
msgstr "Crear y Editar"
#: addons/web/static/src/xml/base.xml:0
msgid "New"
msgstr "Nuevo"
#: addons/web/static/src/xml/base.xml:0
msgid "Duplicate"
msgstr "Duplicar"
#: addons/web/static/src/xml/base.xml:0
msgid "Readonly/Editable"
msgstr "Sólo Lectura/Editable"
#: addons/web/static/src/xml/base.xml:0
msgid "<<"
msgstr "<<"
#: addons/web/static/src/xml/base.xml:0
msgid "0"
msgstr "0"
#: addons/web/static/src/xml/base.xml:0
msgid "/"
msgstr "/"
#: addons/web/static/src/xml/base.xml:0
msgid ">>"
msgstr ">>"
#: addons/web/static/src/xml/base.xml:0
msgid "Add"
msgstr "Añadir"
#: addons/web/static/src/xml/base.xml:0
msgid "Unhandled widget"
msgstr "Widget no controlado"
#: addons/web/static/src/xml/base.xml:0
msgid "?"
msgstr "?"
#: addons/web/static/src/xml/base.xml:0
msgid "#"
msgstr "#"
#: addons/web/static/src/xml/base.xml:0
msgid "Done"
msgstr "Hecho"
#: addons/web/static/src/xml/base.xml:0
msgid "Open..."
msgstr "Abrir..."
#: addons/web/static/src/xml/base.xml:0
msgid "Create..."
msgstr "Crear…"
#: addons/web/static/src/xml/base.xml:0
msgid "Search..."
msgstr "Buscar..."
#: addons/web/static/src/xml/base.xml:0
msgid "..."
msgstr "..."
#: addons/web/static/src/xml/base.xml:0
msgid "Uploading ..."
msgstr "Subiendo ..."
#: addons/web/static/src/xml/base.xml:0
msgid "Select"
msgstr "Seleccionar"
#: addons/web/static/src/xml/base.xml:0
msgid "Save As"
msgstr "Guardar como"
#: addons/web/static/src/xml/base.xml:0
msgid "Clear"
msgstr "Limpiar"
#: addons/web/static/src/xml/base.xml:0
msgid "Advanced Filter"
msgstr "Filtro Avanzado"
#: addons/web/static/src/xml/base.xml:0
msgid "-- Filters --"
msgstr "-- Filtros --"
#: addons/web/static/src/xml/base.xml:0
msgid "-- Actions --"
msgstr "-- Acciones --"
#: addons/web/static/src/xml/base.xml:0
msgid "Save Filter"
msgstr "Guardar Filtro"
#: addons/web/static/src/xml/base.xml:0
msgid "Manage Filters"
msgstr "Gestionar Filtros"
#: addons/web/static/src/xml/base.xml:0
msgid "Filter Name:"
msgstr "Nombre del Filtro"
#: addons/web/static/src/xml/base.xml:0
msgid "(Any existing filter with the same name will be replaced)"
msgstr "(Cualquier filtro existente con el mismo nombre será reemplazado)"
#: addons/web/static/src/xml/base.xml:0
msgid "Any of the following conditions must match"
msgstr "Cualquiera de las condiciones siguientes deben coincidir"
#: addons/web/static/src/xml/base.xml:0
msgid "All the following conditions must match"
msgstr "Todas las condiciones siguientes deben coincidir"
#: addons/web/static/src/xml/base.xml:0
msgid "None of the following conditions must match"
msgstr "Ninguna de las siguientes condiciones deben coincidir"
#: addons/web/static/src/xml/base.xml:0
msgid "Add condition"
msgstr "Añadir condición"
#: addons/web/static/src/xml/base.xml:0
msgid "and"
msgstr "y"
#: addons/web/static/src/xml/base.xml:0
msgid "Cancel"
msgstr "Cancelar"
#: addons/web/static/src/xml/base.xml:0
msgid "Save & New"
msgstr "Guardar y Nuevo"
#: addons/web/static/src/xml/base.xml:0
msgid "Save & Close"
msgstr "Guardar y Cerrar"
#: addons/web/static/src/xml/base.xml:0
msgid "Export"
msgstr "Exportar"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"This wizard will export all data that matches the current search criteria to "
"a CSV file.\n"
" You can export all data or only the fields that can be "
"reimported after modification."
msgstr ""
"Este asistente le exportará todos los datos que coincidan con los criterios "
"de búsqueda actual a un archivo CSV.\n"
" Puede exportar todos los datos o sólo los campos que pueden "
"importarse de nuevo después de la modificación."
#: addons/web/static/src/xml/base.xml:0
msgid "Export Type:"
msgstr "Tipo de Exportación:"
#: addons/web/static/src/xml/base.xml:0
msgid "Import Compatible Export"
msgstr "Exportación compatible con importación"
#: addons/web/static/src/xml/base.xml:0
msgid "Export all Data"
msgstr "Exportar todos los datos"
#: addons/web/static/src/xml/base.xml:0
msgid "Export Formats"
msgstr "Formatos de Exportación"
#: addons/web/static/src/xml/base.xml:0
msgid "Available fields"
msgstr "Campos disponibles"
#: addons/web/static/src/xml/base.xml:0
msgid "Fields to export"
msgstr "Campos a exportar"
#: addons/web/static/src/xml/base.xml:0
msgid "Save fields list"
msgstr "Guardar lista de campos"
#: addons/web/static/src/xml/base.xml:0
msgid "Remove"
msgstr "Eliminar"
#: addons/web/static/src/xml/base.xml:0
msgid "Remove All"
msgstr "Eliminar Todo"
#: addons/web/static/src/xml/base.xml:0
msgid "Name"
msgstr "Nombre"
#: addons/web/static/src/xml/base.xml:0
msgid "&nbsp;"
msgstr "&nbsp;"
#: addons/web/static/src/xml/base.xml:0
msgid "Save as:"
msgstr "Guardar como:"
#: addons/web/static/src/xml/base.xml:0
msgid "Ok"
msgstr "Ok"
#: addons/web/static/src/xml/base.xml:0
msgid "Saved exports:"
msgstr "Exportaciones guardadas:"
#: addons/web/static/src/xml/base.xml:0
msgid "Old Password:"
msgstr "Contraseña anterior:"
#: addons/web/static/src/xml/base.xml:0
msgid "New Password:"
msgstr "Contraseña nueva:"
#: addons/web/static/src/xml/base.xml:0
msgid "Confirm Password:"
msgstr "Confirmar la contraseña:"
#: addons/web/static/src/xml/base.xml:0
msgid "Import"
msgstr "Importar"
#: addons/web/static/src/xml/base.xml:0
msgid "1. Import a .CSV file"
msgstr "1. Importar un archivo .CSV"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"Select a .CSV file to import. If you need a sample of file to import,\n"
" you should use the export tool with the \"Import Compatible\" option."
msgstr ""
"Seleccione un archivo .CSV para importar. Si necesita una muestra de archivo "
"para importar,\n"
" debería usar la herramienta de exportación con la opción de "
"\"Importación Compatible\"."
#: addons/web/static/src/xml/base.xml:0
msgid "CSV File:"
msgstr "Archivo CSV:"
#: addons/web/static/src/xml/base.xml:0
msgid "2. Check your file format"
msgstr "2. Compruebe el formato de archivo"
#: addons/web/static/src/xml/base.xml:0
msgid "Import Options"
msgstr "Opciones de importación"
#: addons/web/static/src/xml/base.xml:0
msgid "Does your file have titles?"
msgstr "¿Tiene su archivo títulos?"
#: addons/web/static/src/xml/base.xml:0
msgid "Separator:"
msgstr "Separador:"
#: addons/web/static/src/xml/base.xml:0
msgid "Delimiter:"
msgstr "Delimitador:"
#: addons/web/static/src/xml/base.xml:0
msgid "Encoding:"
msgstr "Codificación:"
#: addons/web/static/src/xml/base.xml:0
msgid "UTF-8"
msgstr "UTF-8"
#: addons/web/static/src/xml/base.xml:0
msgid "Latin 1"
msgstr "Latin 1"
#: addons/web/static/src/xml/base.xml:0
msgid "Lines to skip"
msgstr "Líneas a omitir"
#: addons/web/static/src/xml/base.xml:0
msgid "The import failed due to:"
msgstr "La importación falló debido a:"
#: addons/web/static/src/xml/base.xml:0
msgid "Here is a preview of the file we could not import:"
msgstr "Esta es una vista previa del archivo que no se pudo importar:"
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP Web"
msgstr "OpenERP Web"
#: addons/web/static/src/xml/base.xml:0
msgid "Version"
msgstr "Versión"
#: addons/web/static/src/xml/base.xml:0
msgid "Copyright © 2011-TODAY OpenERP SA. All Rights Reserved."
msgstr "Copyright © 2011-HOY OpenERP SA. Todos los Derechos Reservados."
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP is a trademark of the"
msgstr "OpenERP es una marca registrada de la"
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP SA Company"
msgstr "Compañía OpenERP SA"
#: addons/web/static/src/xml/base.xml:0
msgid "Licenced under the terms of"
msgstr "Con licencia bajo los términos de"
#: addons/web/static/src/xml/base.xml:0
msgid "GNU Affero General Public License"
msgstr "GNU Affero General Public License"
#: addons/web/static/src/xml/base.xml:0
msgid "About OpenERP"
msgstr "Acerca de OpenERP"
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP"
msgstr "OpenERP"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"is a free enterprise-scale software system that is designed to boost\n"
" productivity and profit through data integration. It connects, "
"improves and\n"
" manages business processes in areas such as sales, finance, "
"supply chain,\n"
" project management, production, services, CRM, etc..."
msgstr ""
"Es un sistema software empresarial-escalar libre diseñado para mejorar\n"
" la productividad y beneficios a través de la integración de "
"datos. Conecta, mejora y\n"
" gestiona los procesos de negocio en áreas como ventas, finanzas, "
"cadena de suministro,\n"
" gestión de proyectos, producción, servicios, CRM, etc..."
#: addons/web/static/src/xml/base.xml:0
msgid ""
"The system is platform-independent, and can be installed on Windows, Mac OS "
"X,\n"
" and various Linux and other Unix-based distributions. Its "
"architecture enables\n"
" new functionality to be rapidly created, modifications to be "
"made to a\n"
" production system and migration to a new version to be "
"straightforward."
msgstr ""
"El sistema es una plataforma-independiente, y puede ser instalada en "
"Windows, Mac OS X,\n"
" y varias distribuciones Linux y otra basadas en Unix. Su "
"arquitectura permite\n"
" crear nuevas funcionalidades rápidamente, las modificaciones a "
"hacer en un\n"
" sistema en producción y migración a una nueva versión son "
"sencillas."
#: addons/web/static/src/xml/base.xml:0
msgid ""
"Depending on your needs, OpenERP is available through a web or application "
"client."
msgstr ""
"Según sus necesidades, OpenERP está disponible mediante un cliente web o una "
"aplicación de escritorio."

710
addons/web/po/es_EC.po Normal file
View File

@ -0,0 +1,710 @@
# Spanish (Ecuador) translation for openerp-web
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openerp-web package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-10-07 10:38+0200\n"
"PO-Revision-Date: 2011-10-07 18:16+0000\n"
"Last-Translator: Cristian Salamea (Gnuthink) <ovnicraft@gmail.com>\n"
"Language-Team: Spanish (Ecuador) <es_EC@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-10-08 05:29+0000\n"
"X-Generator: Launchpad (build 14110)\n"
#: addons/web/static/src/js/view_form.js:355
msgid ""
"Warning, the record has been modified, your changes will be discarded."
msgstr ""
"Aviso, el registro ha sido modificado, sus cambios serán descartados."
#: addons/web/static/src/js/view_form.js:1659
msgid "<em>   Search More...</em>"
msgstr "<em>   Buscar Más...</em>"
#: addons/web/static/src/js/view_form.js:1672
#, python-format
msgid "<em>   Create \"<strong>%s</strong>\"</em>"
msgstr "<em>   Crear \"<strong>%s</strong>\"</em>"
#: addons/web/static/src/js/view_form.js:1678
msgid "<em>   Create and Edit...</em>"
msgstr "<em>   Crear y Editar...</em>"
#: addons/web/static/src/js/views.js:568
msgid "You must choose at least one record."
msgstr "Debe seleccionar al menos un registro."
#: addons/web/static/src/js/views.js:569
msgid "Warning"
msgstr "Advertencia"
#: addons/web/static/src/js/views.js:609
msgid "Translations"
msgstr "Traducciones"
#: addons/web/static/src/js/views.js:614 addons/web/static/src/xml/base.xml:0
msgid "Save"
msgstr "Guardar"
#: addons/web/static/src/js/views.js:615
msgid "Close"
msgstr "Cerrar"
#: addons/web/static/src/xml/base.xml:0
msgid "x"
msgstr "x"
#: addons/web/static/src/xml/base.xml:0
msgid "#{title}"
msgstr "#{title}"
#: addons/web/static/src/xml/base.xml:0
msgid "#{text}"
msgstr "#{text}"
#: addons/web/static/src/xml/base.xml:0
msgid "Powered by"
msgstr "Powered by"
#: addons/web/static/src/xml/base.xml:0
msgid "openerp.com"
msgstr "openerp.com"
#: addons/web/static/src/xml/base.xml:0
msgid "."
msgstr "."
#: addons/web/static/src/xml/base.xml:0
msgid "Loading..."
msgstr "Cargando..."
#: addons/web/static/src/xml/base.xml:0
msgid "Create"
msgstr "Crear"
#: addons/web/static/src/xml/base.xml:0
msgid "Drop"
msgstr "Borrar"
#: addons/web/static/src/xml/base.xml:0
msgid "Backup"
msgstr "Respaldar"
#: addons/web/static/src/xml/base.xml:0
msgid "Restore"
msgstr "Restaurar"
#: addons/web/static/src/xml/base.xml:0
msgid "Password"
msgstr "Contraseña"
#: addons/web/static/src/xml/base.xml:0
msgid "Back to Login"
msgstr "Regresar a inicio de sesión"
#: addons/web/static/src/xml/base.xml:0
msgid "CREATE DATABASE"
msgstr "CREATE DATABASE"
#: addons/web/static/src/xml/base.xml:0
msgid "Master password:"
msgstr "Master password:"
#: addons/web/static/src/xml/base.xml:0
msgid "New database name:"
msgstr "Nuevo nombre de la base de datos:"
#: addons/web/static/src/xml/base.xml:0
msgid "Load Demonstration data:"
msgstr "Cargar datos de demostración"
#: addons/web/static/src/xml/base.xml:0
msgid "Default language:"
msgstr "Lenguaje por defecto:"
#: addons/web/static/src/xml/base.xml:0
msgid "Admin password:"
msgstr "Admin password:"
#: addons/web/static/src/xml/base.xml:0
msgid "Confirm password:"
msgstr "Confirmar password:"
#: addons/web/static/src/xml/base.xml:0
msgid "DROP DATABASE"
msgstr "DROP DATABASE"
#: addons/web/static/src/xml/base.xml:0
msgid "Database:"
msgstr "Base de datos:"
#: addons/web/static/src/xml/base.xml:0
msgid "Master Password:"
msgstr "Master Password:"
#: addons/web/static/src/xml/base.xml:0
msgid "BACKUP DATABASE"
msgstr "BACKUP DATABASE"
#: addons/web/static/src/xml/base.xml:0
msgid "RESTORE DATABASE"
msgstr "RESTORE DATABASE"
#: addons/web/static/src/xml/base.xml:0
msgid "File:"
msgstr "Archivo:"
#: addons/web/static/src/xml/base.xml:0
msgid "CHANGE MASTER PASSWORD"
msgstr "CHANGE MASTER PASSWORD"
#: addons/web/static/src/xml/base.xml:0
msgid "New master password:"
msgstr "New master password:"
#: addons/web/static/src/xml/base.xml:0
msgid "Confirm new master password:"
msgstr "Confirmar nueva master password:"
#: addons/web/static/src/xml/base.xml:0
msgid "User:"
msgstr "Usuario:"
#: addons/web/static/src/xml/base.xml:0
msgid "Password:"
msgstr "Contraseña:"
#: addons/web/static/src/xml/base.xml:0
msgid "Database"
msgstr "Bases de datos"
#: addons/web/static/src/xml/base.xml:0
msgid "Login"
msgstr "Iniciar sesión"
#: addons/web/static/src/xml/base.xml:0
msgid "Bad username or password"
msgstr "Usuario o contraseña incorrectos"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"We think that daily job activities can be more intuitive, efficient, "
"automated, .. and even fun."
msgstr ""
"Pensamos que el trabajo diario debe ser mas intuitivo, eficiente, "
"automatizado, ... e incluso divertido."
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP's vision to be:"
msgstr "OpenERP's vision to be:"
#: addons/web/static/src/xml/base.xml:0
msgid "Full featured"
msgstr "Full featured"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"Today's enterprise challenges are multiple. We provide one module for each "
"need."
msgstr ""
"Today's enterprise challenges are multiple. We provide one module for each "
"need."
#: addons/web/static/src/xml/base.xml:0
msgid "Open Source"
msgstr "Open Source"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"To Build a great product, we rely on the knowledge of thousands of "
"contributors."
msgstr ""
"To Build a great product, we rely on the knowledge of thousands of "
"contributors."
#: addons/web/static/src/xml/base.xml:0
msgid "User Friendly"
msgstr "User Friendly"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"In order to be productive, people need clean and easy to use interface."
msgstr ""
"Para ser productivo, los usuarios necesitan una interfaz limpia y fácil de "
"usar."
#: addons/web/static/src/xml/base.xml:0
msgid "("
msgstr "("
#: addons/web/static/src/xml/base.xml:0
msgid ")"
msgstr ")"
#: addons/web/static/src/xml/base.xml:0
msgid "LOGOUT"
msgstr "LOGOUT"
#: addons/web/static/src/xml/base.xml:0
msgid "&laquo;"
msgstr "&laquo;"
#: addons/web/static/src/xml/base.xml:0
msgid "&raquo;"
msgstr "&raquo;"
#: addons/web/static/src/xml/base.xml:0
msgid "oe_secondary_menu_item"
msgstr "oe_secondary_menu_item"
#: addons/web/static/src/xml/base.xml:0
msgid "oe_secondary_submenu_item"
msgstr "oe_secondary_submenu_item"
#: addons/web/static/src/xml/base.xml:0
msgid "Hide this tip"
msgstr "Ocultar este tip"
#: addons/web/static/src/xml/base.xml:0
msgid "Disable all tips"
msgstr "Desactivar todas las sugerencias"
#: addons/web/static/src/xml/base.xml:0
msgid "View#"
msgstr "View#"
#: addons/web/static/src/xml/base.xml:0
msgid "Fields"
msgstr "Campos"
#: addons/web/static/src/xml/base.xml:0
msgid "View labels"
msgstr "Ver etiquetas"
#: addons/web/static/src/xml/base.xml:0
msgid "Sidebar Relates"
msgstr "Columna lateral relacionada"
#: addons/web/static/src/xml/base.xml:0
msgid "Field"
msgstr "Campo"
#: addons/web/static/src/xml/base.xml:0
msgid ":"
msgstr ":"
#: addons/web/static/src/xml/base.xml:0
msgid "Translate view"
msgstr "Traducir vista"
#: addons/web/static/src/xml/base.xml:0
msgid "Translate sidebar"
msgstr "Traducir Barra lateral"
#: addons/web/static/src/xml/base.xml:0
msgid "Delete"
msgstr "Eliminar"
#: addons/web/static/src/xml/base.xml:0
msgid "First"
msgstr "Primero"
#: addons/web/static/src/xml/base.xml:0
msgid "<"
msgstr "<"
#: addons/web/static/src/xml/base.xml:0
msgid ">"
msgstr ">"
#: addons/web/static/src/xml/base.xml:0
msgid "Last"
msgstr "Último"
#: addons/web/static/src/xml/base.xml:0
msgid "♻"
msgstr "♻"
#: addons/web/static/src/xml/base.xml:0
msgid "Save & Edit"
msgstr "Grabar & Editar"
#: addons/web/static/src/xml/base.xml:0
msgid "Create & Edit"
msgstr "Crear & Editar"
#: addons/web/static/src/xml/base.xml:0
msgid "New"
msgstr "Nuevo"
#: addons/web/static/src/xml/base.xml:0
msgid "Duplicate"
msgstr "Duplicar"
#: addons/web/static/src/xml/base.xml:0
msgid "Readonly/Editable"
msgstr "Sólo Lectura/Editable"
#: addons/web/static/src/xml/base.xml:0
msgid "<<"
msgstr "<<"
#: addons/web/static/src/xml/base.xml:0
msgid "0"
msgstr "0"
#: addons/web/static/src/xml/base.xml:0
msgid "/"
msgstr "/"
#: addons/web/static/src/xml/base.xml:0
msgid ">>"
msgstr ">>"
#: addons/web/static/src/xml/base.xml:0
msgid "Add"
msgstr "Agregar"
#: addons/web/static/src/xml/base.xml:0
msgid "Unhandled widget"
msgstr "Wdiget no controlado"
#: addons/web/static/src/xml/base.xml:0
msgid "?"
msgstr "?"
#: addons/web/static/src/xml/base.xml:0
msgid "#"
msgstr "#"
#: addons/web/static/src/xml/base.xml:0
msgid "Done"
msgstr "Realizado"
#: addons/web/static/src/xml/base.xml:0
msgid "Open..."
msgstr "Abrir…"
#: addons/web/static/src/xml/base.xml:0
msgid "Create..."
msgstr "Crear..."
#: addons/web/static/src/xml/base.xml:0
msgid "Search..."
msgstr "Buscar..."
#: addons/web/static/src/xml/base.xml:0
msgid "..."
msgstr "..."
#: addons/web/static/src/xml/base.xml:0
msgid "Uploading ..."
msgstr "Subiendo..."
#: addons/web/static/src/xml/base.xml:0
msgid "Select"
msgstr "Seleccionar"
#: addons/web/static/src/xml/base.xml:0
msgid "Save As"
msgstr "Guardar Como"
#: addons/web/static/src/xml/base.xml:0
msgid "Clear"
msgstr "Limpiar"
#: addons/web/static/src/xml/base.xml:0
msgid "Advanced Filter"
msgstr "Filtro Avanzado"
#: addons/web/static/src/xml/base.xml:0
msgid "-- Filters --"
msgstr "-- Filtros --"
#: addons/web/static/src/xml/base.xml:0
msgid "-- Actions --"
msgstr "-- Acciones --"
#: addons/web/static/src/xml/base.xml:0
msgid "Save Filter"
msgstr "Guardar Filtro"
#: addons/web/static/src/xml/base.xml:0
msgid "Manage Filters"
msgstr "Gestionar filtros"
#: addons/web/static/src/xml/base.xml:0
msgid "Filter Name:"
msgstr "Nombre del Filtro:"
#: addons/web/static/src/xml/base.xml:0
msgid "(Any existing filter with the same name will be replaced)"
msgstr "(Cualquier filtro existente con el mismo nombre será reemplazado)"
#: addons/web/static/src/xml/base.xml:0
msgid "Any of the following conditions must match"
msgstr "Cualquiera de las siguientes condiciones debe coincidir"
#: addons/web/static/src/xml/base.xml:0
msgid "All the following conditions must match"
msgstr "Todas las siguientes condiciones deben coincidir"
#: addons/web/static/src/xml/base.xml:0
msgid "None of the following conditions must match"
msgstr "Ninguna de las siguientes condiciones debe coincidir"
#: addons/web/static/src/xml/base.xml:0
msgid "Add condition"
msgstr "Agregar condición"
#: addons/web/static/src/xml/base.xml:0
msgid "and"
msgstr "y"
#: addons/web/static/src/xml/base.xml:0
msgid "Cancel"
msgstr "Cancelar"
#: addons/web/static/src/xml/base.xml:0
msgid "Save & New"
msgstr "Grabar & Nuevo"
#: addons/web/static/src/xml/base.xml:0
msgid "Save & Close"
msgstr "Grabar & Cerrar"
#: addons/web/static/src/xml/base.xml:0
msgid "Export"
msgstr "Exportar"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"This wizard will export all data that matches the current search criteria to "
"a CSV file.\n"
" You can export all data or only the fields that can be "
"reimported after modification."
msgstr ""
"Este asistente exportará todos los datos que coincidan con el criterio de "
"búsqueda actual a un archivo CSV.\n"
" Tu puedes exportar todos los datos o solo los campos que serán "
"reimportados después de la modificación."
#: addons/web/static/src/xml/base.xml:0
msgid "Export Type:"
msgstr "Tipo de Exportación"
#: addons/web/static/src/xml/base.xml:0
msgid "Import Compatible Export"
msgstr "Import Compatible Export"
#: addons/web/static/src/xml/base.xml:0
msgid "Export all Data"
msgstr "Exportar todos los datos"
#: addons/web/static/src/xml/base.xml:0
msgid "Export Formats"
msgstr "Formato para exportar"
#: addons/web/static/src/xml/base.xml:0
msgid "Available fields"
msgstr "Campos disponibles"
#: addons/web/static/src/xml/base.xml:0
msgid "Fields to export"
msgstr "Campos a exportar"
#: addons/web/static/src/xml/base.xml:0
msgid "Save fields list"
msgstr "Guardar lista de campos"
#: addons/web/static/src/xml/base.xml:0
msgid "Remove"
msgstr "Eliminar"
#: addons/web/static/src/xml/base.xml:0
msgid "Remove All"
msgstr "Borrar todo"
#: addons/web/static/src/xml/base.xml:0
msgid "Name"
msgstr "Nombre"
#: addons/web/static/src/xml/base.xml:0
msgid "&nbsp;"
msgstr "&nbsp;"
#: addons/web/static/src/xml/base.xml:0
msgid "Save as:"
msgstr "Guardar Como:"
#: addons/web/static/src/xml/base.xml:0
msgid "Ok"
msgstr "Ok"
#: addons/web/static/src/xml/base.xml:0
msgid "Saved exports:"
msgstr "Exportaciones guardadas:"
#: addons/web/static/src/xml/base.xml:0
msgid "Old Password:"
msgstr "Password anterior:"
#: addons/web/static/src/xml/base.xml:0
msgid "New Password:"
msgstr "Nueva Password:"
#: addons/web/static/src/xml/base.xml:0
msgid "Confirm Password:"
msgstr "Confirmar Password:"
#: addons/web/static/src/xml/base.xml:0
msgid "Import"
msgstr "Importar"
#: addons/web/static/src/xml/base.xml:0
msgid "1. Import a .CSV file"
msgstr "1. Importar a archivo .CSV"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"Select a .CSV file to import. If you need a sample of file to import,\n"
" you should use the export tool with the \"Import Compatible\" option."
msgstr ""
"Seleccionar un .archivo CSV para importar. Si necesitas un ejemplo de un "
"archivo para importar,\n"
" you podrías usar la herramienta de exportar con la opción de "
"\"Compatible con Importación\"."
#: addons/web/static/src/xml/base.xml:0
msgid "CSV File:"
msgstr "Archivo CSV:"
#: addons/web/static/src/xml/base.xml:0
msgid "2. Check your file format"
msgstr "Revisa tu formato de archivo"
#: addons/web/static/src/xml/base.xml:0
msgid "Import Options"
msgstr "Opciones para importar"
#: addons/web/static/src/xml/base.xml:0
msgid "Does your file have titles?"
msgstr "Tiene tu archivo títulos ?"
#: addons/web/static/src/xml/base.xml:0
msgid "Separator:"
msgstr "Separador:"
#: addons/web/static/src/xml/base.xml:0
msgid "Delimiter:"
msgstr "Delimitador:"
#: addons/web/static/src/xml/base.xml:0
msgid "Encoding:"
msgstr "Codificación:"
#: addons/web/static/src/xml/base.xml:0
msgid "UTF-8"
msgstr "UTF-8"
#: addons/web/static/src/xml/base.xml:0
msgid "Latin 1"
msgstr "Latin 1"
#: addons/web/static/src/xml/base.xml:0
msgid "Lines to skip"
msgstr "Líneas a omitir"
#: addons/web/static/src/xml/base.xml:0
msgid "The import failed due to:"
msgstr "La importación falló debido a:"
#: addons/web/static/src/xml/base.xml:0
msgid "Here is a preview of the file we could not import:"
msgstr "Aquí está una vista preliminar del archivo que no podemos importar:"
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP Web"
msgstr "OpenERP Web"
#: addons/web/static/src/xml/base.xml:0
msgid "Version"
msgstr "Versión"
#: addons/web/static/src/xml/base.xml:0
msgid "Copyright © 2011-TODAY OpenERP SA. All Rights Reserved."
msgstr "Copyright © 2011-TODAY OpenERP SA. All Rights Reserved."
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP is a trademark of the"
msgstr "OpenERP es una marca registrada de"
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP SA Company"
msgstr "OpenERP SA Company"
#: addons/web/static/src/xml/base.xml:0
msgid "Licenced under the terms of"
msgstr "Licenciado bajo los términos de"
#: addons/web/static/src/xml/base.xml:0
msgid "GNU Affero General Public License"
msgstr "GNU Affero General Public License"
#: addons/web/static/src/xml/base.xml:0
msgid "About OpenERP"
msgstr "Acerca de OpenERP"
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP"
msgstr "OpenERP"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"is a free enterprise-scale software system that is designed to boost\n"
" productivity and profit through data integration. It connects, "
"improves and\n"
" manages business processes in areas such as sales, finance, "
"supply chain,\n"
" project management, production, services, CRM, etc..."
msgstr ""
"is a free enterprise-scale software system that is designed to boost\n"
" productivity and profit through data integration. It connects, "
"improves and\n"
" manages business processes in areas such as sales, finance, "
"supply chain,\n"
" project management, production, services, CRM, etc..."
#: addons/web/static/src/xml/base.xml:0
msgid ""
"The system is platform-independent, and can be installed on Windows, Mac OS "
"X,\n"
" and various Linux and other Unix-based distributions. Its "
"architecture enables\n"
" new functionality to be rapidly created, modifications to be "
"made to a\n"
" production system and migration to a new version to be "
"straightforward."
msgstr ""
"The system is platform-independent, and can be installed on Windows, Mac OS "
"X,\n"
" and various Linux and other Unix-based distributions. Its "
"architecture enables\n"
" new functionality to be rapidly created, modifications to be "
"made to a\n"
" production system and migration to a new version to be "
"straightforward."
#: addons/web/static/src/xml/base.xml:0
msgid ""
"Depending on your needs, OpenERP is available through a web or application "
"client."
msgstr ""
"Dependiendo de tus necesidades, OpenERP está disponible através de un "
"cliente web o escritorio."

677
addons/web/po/et.po Normal file
View File

@ -0,0 +1,677 @@
# Estonian translation for openerp-web
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openerp-web package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-10-07 10:38+0200\n"
"PO-Revision-Date: 2011-10-10 18:30+0000\n"
"Last-Translator: Aare Vesi <Unknown>\n"
"Language-Team: Estonian <et@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-10-11 05:42+0000\n"
"X-Generator: Launchpad (build 14123)\n"
#: addons/web/static/src/js/view_form.js:355
msgid ""
"Warning, the record has been modified, your changes will be discarded."
msgstr ""
#: addons/web/static/src/js/view_form.js:1659
msgid "<em>   Search More...</em>"
msgstr ""
#: addons/web/static/src/js/view_form.js:1672
#, python-format
msgid "<em>   Create \"<strong>%s</strong>\"</em>"
msgstr ""
#: addons/web/static/src/js/view_form.js:1678
msgid "<em>   Create and Edit...</em>"
msgstr ""
#: addons/web/static/src/js/views.js:568
msgid "You must choose at least one record."
msgstr ""
#: addons/web/static/src/js/views.js:569
msgid "Warning"
msgstr "Hoiatus"
#: addons/web/static/src/js/views.js:609
msgid "Translations"
msgstr "Tõlked"
#: addons/web/static/src/js/views.js:614 addons/web/static/src/xml/base.xml:0
msgid "Save"
msgstr "Salvesta"
#: addons/web/static/src/js/views.js:615
msgid "Close"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "x"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "#{title}"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "#{text}"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Powered by"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "openerp.com"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "."
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Loading..."
msgstr "Laadimine..."
#: addons/web/static/src/xml/base.xml:0
msgid "Create"
msgstr "Loo"
#: addons/web/static/src/xml/base.xml:0
msgid "Drop"
msgstr "Hülga"
#: addons/web/static/src/xml/base.xml:0
msgid "Backup"
msgstr "Varunda"
#: addons/web/static/src/xml/base.xml:0
msgid "Restore"
msgstr "Taasta"
#: addons/web/static/src/xml/base.xml:0
msgid "Password"
msgstr "Salasõna"
#: addons/web/static/src/xml/base.xml:0
msgid "Back to Login"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "CREATE DATABASE"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Master password:"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "New database name:"
msgstr "Uue andmebaasi nimi:"
#: addons/web/static/src/xml/base.xml:0
msgid "Load Demonstration data:"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Default language:"
msgstr "Vaikekeel:"
#: addons/web/static/src/xml/base.xml:0
msgid "Admin password:"
msgstr "Admin salasõna:"
#: addons/web/static/src/xml/base.xml:0
msgid "Confirm password:"
msgstr "Salasõna uuesti:"
#: addons/web/static/src/xml/base.xml:0
msgid "DROP DATABASE"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Database:"
msgstr "Andmebaas:"
#: addons/web/static/src/xml/base.xml:0
msgid "Master Password:"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "BACKUP DATABASE"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "RESTORE DATABASE"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "File:"
msgstr "Fail:"
#: addons/web/static/src/xml/base.xml:0
msgid "CHANGE MASTER PASSWORD"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "New master password:"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Confirm new master password:"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "User:"
msgstr "Kasutaja:"
#: addons/web/static/src/xml/base.xml:0
msgid "Password:"
msgstr "Salasõna:"
#: addons/web/static/src/xml/base.xml:0
msgid "Database"
msgstr "Andmebaas"
#: addons/web/static/src/xml/base.xml:0
msgid "Login"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Bad username or password"
msgstr "Vale kasutajanimi või salasõna"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"We think that daily job activities can be more intuitive, efficient, "
"automated, .. and even fun."
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP's vision to be:"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Full featured"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid ""
"Today's enterprise challenges are multiple. We provide one module for each "
"need."
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Open Source"
msgstr "Avatud lähtekoodiga"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"To Build a great product, we rely on the knowledge of thousands of "
"contributors."
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "User Friendly"
msgstr "Kasutajasõbralik"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"In order to be productive, people need clean and easy to use interface."
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "("
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid ")"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "LOGOUT"
msgstr "VÄLJU"
#: addons/web/static/src/xml/base.xml:0
msgid "&laquo;"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "&raquo;"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "oe_secondary_menu_item"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "oe_secondary_submenu_item"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Hide this tip"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Disable all tips"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "View#"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Fields"
msgstr "Väljad"
#: addons/web/static/src/xml/base.xml:0
msgid "View labels"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Sidebar Relates"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Field"
msgstr "Väli"
#: addons/web/static/src/xml/base.xml:0
msgid ":"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Translate view"
msgstr "Tõlke vaade"
#: addons/web/static/src/xml/base.xml:0
msgid "Translate sidebar"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Delete"
msgstr "Kustuta"
#: addons/web/static/src/xml/base.xml:0
msgid "First"
msgstr "Esimene"
#: addons/web/static/src/xml/base.xml:0
msgid "<"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid ">"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Last"
msgstr "Viimane"
#: addons/web/static/src/xml/base.xml:0
msgid "♻"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Save & Edit"
msgstr "Salvesta & Muuda"
#: addons/web/static/src/xml/base.xml:0
msgid "Create & Edit"
msgstr "Loo & Muuda"
#: addons/web/static/src/xml/base.xml:0
msgid "New"
msgstr "Uus"
#: addons/web/static/src/xml/base.xml:0
msgid "Duplicate"
msgstr "Tee koopia"
#: addons/web/static/src/xml/base.xml:0
msgid "Readonly/Editable"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "<<"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "0"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "/"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid ">>"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Add"
msgstr "Lisa"
#: addons/web/static/src/xml/base.xml:0
msgid "Unhandled widget"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "?"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "#"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Done"
msgstr "Valmis"
#: addons/web/static/src/xml/base.xml:0
msgid "Open..."
msgstr "Ava..."
#: addons/web/static/src/xml/base.xml:0
msgid "Create..."
msgstr "Loo..."
#: addons/web/static/src/xml/base.xml:0
msgid "Search..."
msgstr "Otsi..."
#: addons/web/static/src/xml/base.xml:0
msgid "..."
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Uploading ..."
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Select"
msgstr "Vali"
#: addons/web/static/src/xml/base.xml:0
msgid "Save As"
msgstr "Salvesta kui"
#: addons/web/static/src/xml/base.xml:0
msgid "Clear"
msgstr "Tühjenda"
#: addons/web/static/src/xml/base.xml:0
msgid "Advanced Filter"
msgstr "Täiustatud filter"
#: addons/web/static/src/xml/base.xml:0
msgid "-- Filters --"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "-- Actions --"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Save Filter"
msgstr "Salvesta filter"
#: addons/web/static/src/xml/base.xml:0
msgid "Manage Filters"
msgstr "Halda filtreid"
#: addons/web/static/src/xml/base.xml:0
msgid "Filter Name:"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "(Any existing filter with the same name will be replaced)"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Any of the following conditions must match"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "All the following conditions must match"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "None of the following conditions must match"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Add condition"
msgstr "Lisa tingimus"
#: addons/web/static/src/xml/base.xml:0
msgid "and"
msgstr "ja"
#: addons/web/static/src/xml/base.xml:0
msgid "Cancel"
msgstr "Tühista"
#: addons/web/static/src/xml/base.xml:0
msgid "Save & New"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Save & Close"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Export"
msgstr "Eksport"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"This wizard will export all data that matches the current search criteria to "
"a CSV file.\n"
" You can export all data or only the fields that can be "
"reimported after modification."
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Export Type:"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Import Compatible Export"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Export all Data"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Export Formats"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Available fields"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Fields to export"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Save fields list"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Remove"
msgstr "Eemalda"
#: addons/web/static/src/xml/base.xml:0
msgid "Remove All"
msgstr "Eemalda kõik"
#: addons/web/static/src/xml/base.xml:0
msgid "Name"
msgstr "Nimi"
#: addons/web/static/src/xml/base.xml:0
msgid "&nbsp;"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Save as:"
msgstr "Salvesta kui:"
#: addons/web/static/src/xml/base.xml:0
msgid "Ok"
msgstr "Ok"
#: addons/web/static/src/xml/base.xml:0
msgid "Saved exports:"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Old Password:"
msgstr "Vana salasõna:"
#: addons/web/static/src/xml/base.xml:0
msgid "New Password:"
msgstr "Uus salasõna:"
#: addons/web/static/src/xml/base.xml:0
msgid "Confirm Password:"
msgstr "Kinnita salasõna:"
#: addons/web/static/src/xml/base.xml:0
msgid "Import"
msgstr "Import"
#: addons/web/static/src/xml/base.xml:0
msgid "1. Import a .CSV file"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid ""
"Select a .CSV file to import. If you need a sample of file to import,\n"
" you should use the export tool with the \"Import Compatible\" option."
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "CSV File:"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "2. Check your file format"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Import Options"
msgstr "Impordi valikud"
#: addons/web/static/src/xml/base.xml:0
msgid "Does your file have titles?"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Separator:"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Delimiter:"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Encoding:"
msgstr "Kodeering:"
#: addons/web/static/src/xml/base.xml:0
msgid "UTF-8"
msgstr "UTF-8"
#: addons/web/static/src/xml/base.xml:0
msgid "Latin 1"
msgstr "Latin 1"
#: addons/web/static/src/xml/base.xml:0
msgid "Lines to skip"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "The import failed due to:"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Here is a preview of the file we could not import:"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP Web"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Version"
msgstr "Versioon"
#: addons/web/static/src/xml/base.xml:0
msgid "Copyright © 2011-TODAY OpenERP SA. All Rights Reserved."
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP is a trademark of the"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP SA Company"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Licenced under the terms of"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "GNU Affero General Public License"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "About OpenERP"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP"
msgstr "OpenERP"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"is a free enterprise-scale software system that is designed to boost\n"
" productivity and profit through data integration. It connects, "
"improves and\n"
" manages business processes in areas such as sales, finance, "
"supply chain,\n"
" project management, production, services, CRM, etc..."
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid ""
"The system is platform-independent, and can be installed on Windows, Mac OS "
"X,\n"
" and various Linux and other Unix-based distributions. Its "
"architecture enables\n"
" new functionality to be rapidly created, modifications to be "
"made to a\n"
" production system and migration to a new version to be "
"straightforward."
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid ""
"Depending on your needs, OpenERP is available through a web or application "
"client."
msgstr ""

678
addons/web/po/fr.po Normal file
View File

@ -0,0 +1,678 @@
# French translation for openerp-web
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openerp-web package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-10-07 10:38+0200\n"
"PO-Revision-Date: 2011-10-23 12:20+0000\n"
"Last-Translator: Xavier (Open ERP) <Unknown>\n"
"Language-Team: French <fr@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-10-24 05:18+0000\n"
"X-Generator: Launchpad (build 14185)\n"
#: addons/web/static/src/js/view_form.js:355
msgid ""
"Warning, the record has been modified, your changes will be discarded."
msgstr ""
"Attention, l'enregistrement a été modifié, vos changements seront perdus."
#: addons/web/static/src/js/view_form.js:1659
msgid "<em>   Search More...</em>"
msgstr ""
#: addons/web/static/src/js/view_form.js:1672
#, python-format
msgid "<em>   Create \"<strong>%s</strong>\"</em>"
msgstr ""
#: addons/web/static/src/js/view_form.js:1678
msgid "<em>   Create and Edit...</em>"
msgstr ""
#: addons/web/static/src/js/views.js:568
msgid "You must choose at least one record."
msgstr "Vous devez choisir au moins un enregistrement"
#: addons/web/static/src/js/views.js:569
msgid "Warning"
msgstr "Attention"
#: addons/web/static/src/js/views.js:609
msgid "Translations"
msgstr "Traductions"
#: addons/web/static/src/js/views.js:614 addons/web/static/src/xml/base.xml:0
msgid "Save"
msgstr "Enregistrer"
#: addons/web/static/src/js/views.js:615
msgid "Close"
msgstr "Fermer"
#: addons/web/static/src/xml/base.xml:0
msgid "x"
msgstr "x"
#: addons/web/static/src/xml/base.xml:0
msgid "#{title}"
msgstr "#{title}"
#: addons/web/static/src/xml/base.xml:0
msgid "#{text}"
msgstr "#{text}"
#: addons/web/static/src/xml/base.xml:0
msgid "Powered by"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "openerp.com"
msgstr "openerp.com"
#: addons/web/static/src/xml/base.xml:0
msgid "."
msgstr "."
#: addons/web/static/src/xml/base.xml:0
msgid "Loading..."
msgstr "Chargement..."
#: addons/web/static/src/xml/base.xml:0
msgid "Create"
msgstr "Créer"
#: addons/web/static/src/xml/base.xml:0
msgid "Drop"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Backup"
msgstr "Archiver"
#: addons/web/static/src/xml/base.xml:0
msgid "Restore"
msgstr "Restaurer"
#: addons/web/static/src/xml/base.xml:0
msgid "Password"
msgstr "Mot de passe"
#: addons/web/static/src/xml/base.xml:0
msgid "Back to Login"
msgstr "Retour à la page d'authentification"
#: addons/web/static/src/xml/base.xml:0
msgid "CREATE DATABASE"
msgstr "CRÉER LA BASE DE DONNÉES"
#: addons/web/static/src/xml/base.xml:0
msgid "Master password:"
msgstr "Mot de passe principal:"
#: addons/web/static/src/xml/base.xml:0
msgid "New database name:"
msgstr "Nom de la nouvelle base de données :"
#: addons/web/static/src/xml/base.xml:0
msgid "Load Demonstration data:"
msgstr "Charger les données de démonstration:"
#: addons/web/static/src/xml/base.xml:0
msgid "Default language:"
msgstr "Langue par défaut :"
#: addons/web/static/src/xml/base.xml:0
msgid "Admin password:"
msgstr "Mot de passe administrateur:"
#: addons/web/static/src/xml/base.xml:0
msgid "Confirm password:"
msgstr "Confirmer le mot de passe:"
#: addons/web/static/src/xml/base.xml:0
msgid "DROP DATABASE"
msgstr "SUPPRIMER LA BASE DE DONNÉES"
#: addons/web/static/src/xml/base.xml:0
msgid "Database:"
msgstr "Base de données :"
#: addons/web/static/src/xml/base.xml:0
msgid "Master Password:"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "BACKUP DATABASE"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "RESTORE DATABASE"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "File:"
msgstr "Fichier :"
#: addons/web/static/src/xml/base.xml:0
msgid "CHANGE MASTER PASSWORD"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "New master password:"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Confirm new master password:"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "User:"
msgstr "Utilisateur :"
#: addons/web/static/src/xml/base.xml:0
msgid "Password:"
msgstr "Mot de passe :"
#: addons/web/static/src/xml/base.xml:0
msgid "Database"
msgstr "Base de données"
#: addons/web/static/src/xml/base.xml:0
msgid "Login"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Bad username or password"
msgstr "Mauvais identfiant ou mot de passe"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"We think that daily job activities can be more intuitive, efficient, "
"automated, .. and even fun."
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP's vision to be:"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Full featured"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid ""
"Today's enterprise challenges are multiple. We provide one module for each "
"need."
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Open Source"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid ""
"To Build a great product, we rely on the knowledge of thousands of "
"contributors."
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "User Friendly"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid ""
"In order to be productive, people need clean and easy to use interface."
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "("
msgstr "("
#: addons/web/static/src/xml/base.xml:0
msgid ")"
msgstr ")"
#: addons/web/static/src/xml/base.xml:0
msgid "LOGOUT"
msgstr "DÉCONNEXION"
#: addons/web/static/src/xml/base.xml:0
msgid "&laquo;"
msgstr "&laquo;"
#: addons/web/static/src/xml/base.xml:0
msgid "&raquo;"
msgstr "&raquo;"
#: addons/web/static/src/xml/base.xml:0
msgid "oe_secondary_menu_item"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "oe_secondary_submenu_item"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Hide this tip"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Disable all tips"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "View#"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Fields"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "View labels"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Sidebar Relates"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Field"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid ":"
msgstr ":"
#: addons/web/static/src/xml/base.xml:0
msgid "Translate view"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Translate sidebar"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Delete"
msgstr "Supprimer"
#: addons/web/static/src/xml/base.xml:0
msgid "First"
msgstr "Premier"
#: addons/web/static/src/xml/base.xml:0
msgid "<"
msgstr "<"
#: addons/web/static/src/xml/base.xml:0
msgid ">"
msgstr ">"
#: addons/web/static/src/xml/base.xml:0
msgid "Last"
msgstr "Dernier"
#: addons/web/static/src/xml/base.xml:0
msgid "♻"
msgstr "♻"
#: addons/web/static/src/xml/base.xml:0
msgid "Save & Edit"
msgstr "Enregistrer et éditer"
#: addons/web/static/src/xml/base.xml:0
msgid "Create & Edit"
msgstr "Créer et éditer"
#: addons/web/static/src/xml/base.xml:0
msgid "New"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Duplicate"
msgstr "Dupliquer"
#: addons/web/static/src/xml/base.xml:0
msgid "Readonly/Editable"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "<<"
msgstr "<<"
#: addons/web/static/src/xml/base.xml:0
msgid "0"
msgstr "0"
#: addons/web/static/src/xml/base.xml:0
msgid "/"
msgstr "/"
#: addons/web/static/src/xml/base.xml:0
msgid ">>"
msgstr ">>"
#: addons/web/static/src/xml/base.xml:0
msgid "Add"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Unhandled widget"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "?"
msgstr "?"
#: addons/web/static/src/xml/base.xml:0
msgid "#"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Done"
msgstr "Terminé"
#: addons/web/static/src/xml/base.xml:0
msgid "Open..."
msgstr "Ouvrir..."
#: addons/web/static/src/xml/base.xml:0
msgid "Create..."
msgstr "Créer..."
#: addons/web/static/src/xml/base.xml:0
msgid "Search..."
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "..."
msgstr "..."
#: addons/web/static/src/xml/base.xml:0
msgid "Uploading ..."
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Select"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Save As"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Clear"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Advanced Filter"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "-- Filters --"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "-- Actions --"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Save Filter"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Manage Filters"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Filter Name:"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "(Any existing filter with the same name will be replaced)"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Any of the following conditions must match"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "All the following conditions must match"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "None of the following conditions must match"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Add condition"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "and"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Cancel"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Save & New"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Save & Close"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Export"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid ""
"This wizard will export all data that matches the current search criteria to "
"a CSV file.\n"
" You can export all data or only the fields that can be "
"reimported after modification."
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Export Type:"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Import Compatible Export"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Export all Data"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Export Formats"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Available fields"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Fields to export"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Save fields list"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Remove"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Remove All"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Name"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "&nbsp;"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Save as:"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Ok"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Saved exports:"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Old Password:"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "New Password:"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Confirm Password:"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Import"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "1. Import a .CSV file"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid ""
"Select a .CSV file to import. If you need a sample of file to import,\n"
" you should use the export tool with the \"Import Compatible\" option."
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "CSV File:"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "2. Check your file format"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Import Options"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Does your file have titles?"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Separator:"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Delimiter:"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Encoding:"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "UTF-8"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Latin 1"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Lines to skip"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "The import failed due to:"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Here is a preview of the file we could not import:"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP Web"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Version"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Copyright © 2011-TODAY OpenERP SA. All Rights Reserved."
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP is a trademark of the"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP SA Company"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Licenced under the terms of"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "GNU Affero General Public License"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "About OpenERP"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid ""
"is a free enterprise-scale software system that is designed to boost\n"
" productivity and profit through data integration. It connects, "
"improves and\n"
" manages business processes in areas such as sales, finance, "
"supply chain,\n"
" project management, production, services, CRM, etc..."
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid ""
"The system is platform-independent, and can be installed on Windows, Mac OS "
"X,\n"
" and various Linux and other Unix-based distributions. Its "
"architecture enables\n"
" new functionality to be rapidly created, modifications to be "
"made to a\n"
" production system and migration to a new version to be "
"straightforward."
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid ""
"Depending on your needs, OpenERP is available through a web or application "
"client."
msgstr ""

709
addons/web/po/gl.po Normal file
View File

@ -0,0 +1,709 @@
# Galician translation for openerp-web
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openerp-web package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-10-07 10:38+0200\n"
"PO-Revision-Date: 2011-10-19 07:54+0000\n"
"Last-Translator: Amós Oviedo <Unknown>\n"
"Language-Team: Galician <gl@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-10-20 04:48+0000\n"
"X-Generator: Launchpad (build 14165)\n"
#: addons/web/static/src/js/view_form.js:355
msgid ""
"Warning, the record has been modified, your changes will be discarded."
msgstr "Advertencia, o rexistro modificouse, os cambios serán descartados."
#: addons/web/static/src/js/view_form.js:1659
msgid "<em>   Search More...</em>"
msgstr "<em>   Buscar máis...</em>"
#: addons/web/static/src/js/view_form.js:1672
#, python-format
msgid "<em>   Create \"<strong>%s</strong>\"</em>"
msgstr "<em>   Crear \"<strong>%s</strong>\"</em>"
#: addons/web/static/src/js/view_form.js:1678
msgid "<em>   Create and Edit...</em>"
msgstr "<em>   Crear e Editar...</em>"
#: addons/web/static/src/js/views.js:568
msgid "You must choose at least one record."
msgstr "Debe seleccionar polo menos un rexistro."
#: addons/web/static/src/js/views.js:569
msgid "Warning"
msgstr "Advertencia"
#: addons/web/static/src/js/views.js:609
msgid "Translations"
msgstr "Traducións"
#: addons/web/static/src/js/views.js:614 addons/web/static/src/xml/base.xml:0
msgid "Save"
msgstr "Gardar"
#: addons/web/static/src/js/views.js:615
msgid "Close"
msgstr "Pechar"
#: addons/web/static/src/xml/base.xml:0
msgid "x"
msgstr "x"
#: addons/web/static/src/xml/base.xml:0
msgid "#{title}"
msgstr "#{title}"
#: addons/web/static/src/xml/base.xml:0
msgid "#{text}"
msgstr "#{text}"
#: addons/web/static/src/xml/base.xml:0
msgid "Powered by"
msgstr "Desenvolvido por"
#: addons/web/static/src/xml/base.xml:0
msgid "openerp.com"
msgstr "openerp.com"
#: addons/web/static/src/xml/base.xml:0
msgid "."
msgstr "."
#: addons/web/static/src/xml/base.xml:0
msgid "Loading..."
msgstr "Cargando…"
#: addons/web/static/src/xml/base.xml:0
msgid "Create"
msgstr "Crear"
#: addons/web/static/src/xml/base.xml:0
msgid "Drop"
msgstr "Eliminar"
#: addons/web/static/src/xml/base.xml:0
msgid "Backup"
msgstr "Copia de seguridade"
#: addons/web/static/src/xml/base.xml:0
msgid "Restore"
msgstr "Restaurar"
#: addons/web/static/src/xml/base.xml:0
msgid "Password"
msgstr "Contrasinal"
#: addons/web/static/src/xml/base.xml:0
msgid "Back to Login"
msgstr "Voltar ó Inicio de sesión"
#: addons/web/static/src/xml/base.xml:0
msgid "CREATE DATABASE"
msgstr "CREAR BASE DE DATOS"
#: addons/web/static/src/xml/base.xml:0
msgid "Master password:"
msgstr "Contrasinal maestra"
#: addons/web/static/src/xml/base.xml:0
msgid "New database name:"
msgstr "Nome da nova base de datos:"
#: addons/web/static/src/xml/base.xml:0
msgid "Load Demonstration data:"
msgstr "Cargar datos de demostración:"
#: addons/web/static/src/xml/base.xml:0
msgid "Default language:"
msgstr "Idioma por defecto:"
#: addons/web/static/src/xml/base.xml:0
msgid "Admin password:"
msgstr "Contrasinal de Admin:"
#: addons/web/static/src/xml/base.xml:0
msgid "Confirm password:"
msgstr "Confirmar contrasinal:"
#: addons/web/static/src/xml/base.xml:0
msgid "DROP DATABASE"
msgstr "ELIMINAR BASE DE DATOS"
#: addons/web/static/src/xml/base.xml:0
msgid "Database:"
msgstr "Base de datos:"
#: addons/web/static/src/xml/base.xml:0
msgid "Master Password:"
msgstr "Contrasinal Maestra"
#: addons/web/static/src/xml/base.xml:0
msgid "BACKUP DATABASE"
msgstr "COPIA DE SEGURIDADE DA BASE DE DATOS"
#: addons/web/static/src/xml/base.xml:0
msgid "RESTORE DATABASE"
msgstr "RESTAURAR BASE DE DATOS"
#: addons/web/static/src/xml/base.xml:0
msgid "File:"
msgstr "Arquivo:"
#: addons/web/static/src/xml/base.xml:0
msgid "CHANGE MASTER PASSWORD"
msgstr "CAMBIAR CONTRASINAL MAESTRA"
#: addons/web/static/src/xml/base.xml:0
msgid "New master password:"
msgstr "Nova contrasinal maestra:"
#: addons/web/static/src/xml/base.xml:0
msgid "Confirm new master password:"
msgstr "Confirmar nova contrasinal maestra:"
#: addons/web/static/src/xml/base.xml:0
msgid "User:"
msgstr "Usuario:"
#: addons/web/static/src/xml/base.xml:0
msgid "Password:"
msgstr "Contrasinal:"
#: addons/web/static/src/xml/base.xml:0
msgid "Database"
msgstr "Base de datos"
#: addons/web/static/src/xml/base.xml:0
msgid "Login"
msgstr "Inicio de sesión"
#: addons/web/static/src/xml/base.xml:0
msgid "Bad username or password"
msgstr "Nome de usuario ou contrasinal incorrectos"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"We think that daily job activities can be more intuitive, efficient, "
"automated, .. and even fun."
msgstr ""
"Cremos que as actividades diarias de traballo poden ser máis intuitivas, "
"eficientes e automatizadas, .. e mesmo divertidas."
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP's vision to be:"
msgstr "Los obxectivos de OpenERP son ser:"
#: addons/web/static/src/xml/base.xml:0
msgid "Full featured"
msgstr "Con todas as funcións"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"Today's enterprise challenges are multiple. We provide one module for each "
"need."
msgstr ""
"Os retos actuais da empresa son múltiples. Ofrecemos un módulo para cada "
"necesidade."
#: addons/web/static/src/xml/base.xml:0
msgid "Open Source"
msgstr "Código aberto"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"To Build a great product, we rely on the knowledge of thousands of "
"contributors."
msgstr ""
"Para construir un gran producto, contamos coos coñecementos de miles de "
"contribuíntes."
#: addons/web/static/src/xml/base.xml:0
msgid "User Friendly"
msgstr "Sinxelo de usar"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"In order to be productive, people need clean and easy to use interface."
msgstr ""
"Co fin de ser produtivo, a xente necesita unha interface clara e sinxela de "
"usar."
#: addons/web/static/src/xml/base.xml:0
msgid "("
msgstr "("
#: addons/web/static/src/xml/base.xml:0
msgid ")"
msgstr ")"
#: addons/web/static/src/xml/base.xml:0
msgid "LOGOUT"
msgstr "PECHAR SESIÓN"
#: addons/web/static/src/xml/base.xml:0
msgid "&laquo;"
msgstr "&laquo;"
#: addons/web/static/src/xml/base.xml:0
msgid "&raquo;"
msgstr "&raquo;"
#: addons/web/static/src/xml/base.xml:0
msgid "oe_secondary_menu_item"
msgstr "oe_secondary_menu_item"
#: addons/web/static/src/xml/base.xml:0
msgid "oe_secondary_submenu_item"
msgstr "oe_secondary_submenu_item"
#: addons/web/static/src/xml/base.xml:0
msgid "Hide this tip"
msgstr "Ocultar esta suxerencia"
#: addons/web/static/src/xml/base.xml:0
msgid "Disable all tips"
msgstr "Desactivar todas as suxerencias"
#: addons/web/static/src/xml/base.xml:0
msgid "View#"
msgstr "Vista#"
#: addons/web/static/src/xml/base.xml:0
msgid "Fields"
msgstr "Campos"
#: addons/web/static/src/xml/base.xml:0
msgid "View labels"
msgstr "Ver etiquetas"
#: addons/web/static/src/xml/base.xml:0
msgid "Sidebar Relates"
msgstr "Relaciónase coa barra lateral"
#: addons/web/static/src/xml/base.xml:0
msgid "Field"
msgstr "Campo"
#: addons/web/static/src/xml/base.xml:0
msgid ":"
msgstr ":"
#: addons/web/static/src/xml/base.xml:0
msgid "Translate view"
msgstr "Traducir vista"
#: addons/web/static/src/xml/base.xml:0
msgid "Translate sidebar"
msgstr "Traducir barra lateral"
#: addons/web/static/src/xml/base.xml:0
msgid "Delete"
msgstr "Borrar"
#: addons/web/static/src/xml/base.xml:0
msgid "First"
msgstr "Primeiro"
#: addons/web/static/src/xml/base.xml:0
msgid "<"
msgstr "<"
#: addons/web/static/src/xml/base.xml:0
msgid ">"
msgstr ">"
#: addons/web/static/src/xml/base.xml:0
msgid "Last"
msgstr "Último"
#: addons/web/static/src/xml/base.xml:0
msgid "♻"
msgstr "♻"
#: addons/web/static/src/xml/base.xml:0
msgid "Save & Edit"
msgstr "Gardar e Editar"
#: addons/web/static/src/xml/base.xml:0
msgid "Create & Edit"
msgstr "Crear e Editar"
#: addons/web/static/src/xml/base.xml:0
msgid "New"
msgstr "Novo"
#: addons/web/static/src/xml/base.xml:0
msgid "Duplicate"
msgstr "Duplicar"
#: addons/web/static/src/xml/base.xml:0
msgid "Readonly/Editable"
msgstr "Só Lectura/Editable"
#: addons/web/static/src/xml/base.xml:0
msgid "<<"
msgstr "<<"
#: addons/web/static/src/xml/base.xml:0
msgid "0"
msgstr "0"
#: addons/web/static/src/xml/base.xml:0
msgid "/"
msgstr "/"
#: addons/web/static/src/xml/base.xml:0
msgid ">>"
msgstr ">>"
#: addons/web/static/src/xml/base.xml:0
msgid "Add"
msgstr "Engadir"
#: addons/web/static/src/xml/base.xml:0
msgid "Unhandled widget"
msgstr "Widget non controlado"
#: addons/web/static/src/xml/base.xml:0
msgid "?"
msgstr "?"
#: addons/web/static/src/xml/base.xml:0
msgid "#"
msgstr "#"
#: addons/web/static/src/xml/base.xml:0
msgid "Done"
msgstr "Feito"
#: addons/web/static/src/xml/base.xml:0
msgid "Open..."
msgstr "Abrir..."
#: addons/web/static/src/xml/base.xml:0
msgid "Create..."
msgstr "Crear…"
#: addons/web/static/src/xml/base.xml:0
msgid "Search..."
msgstr "Buscar..."
#: addons/web/static/src/xml/base.xml:0
msgid "..."
msgstr "…"
#: addons/web/static/src/xml/base.xml:0
msgid "Uploading ..."
msgstr "Subindo ..."
#: addons/web/static/src/xml/base.xml:0
msgid "Select"
msgstr "Seleccionar"
#: addons/web/static/src/xml/base.xml:0
msgid "Save As"
msgstr "Gardar como"
#: addons/web/static/src/xml/base.xml:0
msgid "Clear"
msgstr "Limpar"
#: addons/web/static/src/xml/base.xml:0
msgid "Advanced Filter"
msgstr "Filtro Avanzado"
#: addons/web/static/src/xml/base.xml:0
msgid "-- Filters --"
msgstr "-- Filtros --"
#: addons/web/static/src/xml/base.xml:0
msgid "-- Actions --"
msgstr "-- Accións --"
#: addons/web/static/src/xml/base.xml:0
msgid "Save Filter"
msgstr "Gardar Filtro"
#: addons/web/static/src/xml/base.xml:0
msgid "Manage Filters"
msgstr "Xestionar filtros"
#: addons/web/static/src/xml/base.xml:0
msgid "Filter Name:"
msgstr "Nome do Filtro"
#: addons/web/static/src/xml/base.xml:0
msgid "(Any existing filter with the same name will be replaced)"
msgstr "(Calquer filtro existente co mesmo nome será reemplazado)"
#: addons/web/static/src/xml/base.xml:0
msgid "Any of the following conditions must match"
msgstr "Calquera das condicións seguintes deben coincidir"
#: addons/web/static/src/xml/base.xml:0
msgid "All the following conditions must match"
msgstr "Todas as condicións seguintes deben coincidir"
#: addons/web/static/src/xml/base.xml:0
msgid "None of the following conditions must match"
msgstr "Ningunha das seguintes condicións deben coincidir"
#: addons/web/static/src/xml/base.xml:0
msgid "Add condition"
msgstr "Engadir condición"
#: addons/web/static/src/xml/base.xml:0
msgid "and"
msgstr "e"
#: addons/web/static/src/xml/base.xml:0
msgid "Cancel"
msgstr "Cancelar"
#: addons/web/static/src/xml/base.xml:0
msgid "Save & New"
msgstr "Gardar e Novo"
#: addons/web/static/src/xml/base.xml:0
msgid "Save & Close"
msgstr "Gardar e Pechar"
#: addons/web/static/src/xml/base.xml:0
msgid "Export"
msgstr "Exportar"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"This wizard will export all data that matches the current search criteria to "
"a CSV file.\n"
" You can export all data or only the fields that can be "
"reimported after modification."
msgstr ""
"Este asistente exportaralle todos os datos que coincidan cos criterios de "
"procura actual a un arquivo CSV.\n"
" Pode exportar todos os datos ou só os campos que poden "
"importarse de novo despois da modificación."
#: addons/web/static/src/xml/base.xml:0
msgid "Export Type:"
msgstr "Tipo de Exportación:"
#: addons/web/static/src/xml/base.xml:0
msgid "Import Compatible Export"
msgstr "Exportación compatible con importación"
#: addons/web/static/src/xml/base.xml:0
msgid "Export all Data"
msgstr "Exportar todos os datos"
#: addons/web/static/src/xml/base.xml:0
msgid "Export Formats"
msgstr "Formatos de Exportación"
#: addons/web/static/src/xml/base.xml:0
msgid "Available fields"
msgstr "Campos dispoñibles"
#: addons/web/static/src/xml/base.xml:0
msgid "Fields to export"
msgstr "Campos a exportar"
#: addons/web/static/src/xml/base.xml:0
msgid "Save fields list"
msgstr "Gardar lista de campos"
#: addons/web/static/src/xml/base.xml:0
msgid "Remove"
msgstr "Eliminar"
#: addons/web/static/src/xml/base.xml:0
msgid "Remove All"
msgstr "Eliminar Todo"
#: addons/web/static/src/xml/base.xml:0
msgid "Name"
msgstr "Nome"
#: addons/web/static/src/xml/base.xml:0
msgid "&nbsp;"
msgstr "&nbsp;"
#: addons/web/static/src/xml/base.xml:0
msgid "Save as:"
msgstr "Gardar como:"
#: addons/web/static/src/xml/base.xml:0
msgid "Ok"
msgstr "Ok"
#: addons/web/static/src/xml/base.xml:0
msgid "Saved exports:"
msgstr "Exportacións gardadas:"
#: addons/web/static/src/xml/base.xml:0
msgid "Old Password:"
msgstr "Contrasinal anterior:"
#: addons/web/static/src/xml/base.xml:0
msgid "New Password:"
msgstr "Contrasinal nova:"
#: addons/web/static/src/xml/base.xml:0
msgid "Confirm Password:"
msgstr "Confirmar contrasinal:"
#: addons/web/static/src/xml/base.xml:0
msgid "Import"
msgstr "Importar"
#: addons/web/static/src/xml/base.xml:0
msgid "1. Import a .CSV file"
msgstr "1. Importar un arquivo .CSV"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"Select a .CSV file to import. If you need a sample of file to import,\n"
" you should use the export tool with the \"Import Compatible\" option."
msgstr ""
"Seleccione un arquivo .CSV para importar. Se necesita unha mostra de arquivo "
"para importar,\n"
" debería usar a ferramenta de exportación coa opción de \"Importación "
"Compatible\"."
#: addons/web/static/src/xml/base.xml:0
msgid "CSV File:"
msgstr "Arquivo CSV:"
#: addons/web/static/src/xml/base.xml:0
msgid "2. Check your file format"
msgstr "2. Comprobe o formato de arquivo"
#: addons/web/static/src/xml/base.xml:0
msgid "Import Options"
msgstr "Importar opcións"
#: addons/web/static/src/xml/base.xml:0
msgid "Does your file have titles?"
msgstr "¿Ten o seu arquivo títulos?"
#: addons/web/static/src/xml/base.xml:0
msgid "Separator:"
msgstr "Separador:"
#: addons/web/static/src/xml/base.xml:0
msgid "Delimiter:"
msgstr "Delimitador:"
#: addons/web/static/src/xml/base.xml:0
msgid "Encoding:"
msgstr "Codificación:"
#: addons/web/static/src/xml/base.xml:0
msgid "UTF-8"
msgstr "UTF-8"
#: addons/web/static/src/xml/base.xml:0
msgid "Latin 1"
msgstr "Latin 1"
#: addons/web/static/src/xml/base.xml:0
msgid "Lines to skip"
msgstr "Liñas a omitir"
#: addons/web/static/src/xml/base.xml:0
msgid "The import failed due to:"
msgstr "A importación fallou debido a:"
#: addons/web/static/src/xml/base.xml:0
msgid "Here is a preview of the file we could not import:"
msgstr "Esta é a vista previa do arquivo que non se pode importar:"
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP Web"
msgstr "OpenERP Web"
#: addons/web/static/src/xml/base.xml:0
msgid "Version"
msgstr "Versión"
#: addons/web/static/src/xml/base.xml:0
msgid "Copyright © 2011-TODAY OpenERP SA. All Rights Reserved."
msgstr "Copyright © 2011-HOXE OpenERP SA. Todos os Dereitos Reservados."
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP is a trademark of the"
msgstr "OpenERP é unha marca rexistrada da"
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP SA Company"
msgstr "Compañía OpenERP SA"
#: addons/web/static/src/xml/base.xml:0
msgid "Licenced under the terms of"
msgstr "Con licencia baixo os termos de"
#: addons/web/static/src/xml/base.xml:0
msgid "GNU Affero General Public License"
msgstr "GNU Affero General Public License"
#: addons/web/static/src/xml/base.xml:0
msgid "About OpenERP"
msgstr "Acerca de OpenERP"
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP"
msgstr "OpenERP"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"is a free enterprise-scale software system that is designed to boost\n"
" productivity and profit through data integration. It connects, "
"improves and\n"
" manages business processes in areas such as sales, finance, "
"supply chain,\n"
" project management, production, services, CRM, etc..."
msgstr ""
"É un sistema software empresarial-escalar libre deseñado para mellorar\n"
" a productividade y beneficios a través da integración de datos. "
"Conecta, mellora e\n"
" xestiona os procesos de negocio en áreas como ventas, finanzas, "
"cadena de suministro,\n"
" xestión de proxectos, producción, servizos, CRM, etc..."
#: addons/web/static/src/xml/base.xml:0
msgid ""
"The system is platform-independent, and can be installed on Windows, Mac OS "
"X,\n"
" and various Linux and other Unix-based distributions. Its "
"architecture enables\n"
" new functionality to be rapidly created, modifications to be "
"made to a\n"
" production system and migration to a new version to be "
"straightforward."
msgstr ""
"O sistema é unha plataforma-independente, e pode ser instalada en Windows, "
"Mac OS X,\n"
" e varias distribucións Linux e outra basadas en Unix. A súa "
"arquitectura permite\n"
" crear novas funcionalidades rápidamente, as modificacións a "
"facer nun\n"
" sistema en producción e migración a unha nova versión son "
"sinxelas."
#: addons/web/static/src/xml/base.xml:0
msgid ""
"Depending on your needs, OpenERP is available through a web or application "
"client."
msgstr ""
"Segundo as súas necesidades, OpenERP está dispoñible a través dun cliente "
"web ou unha aplicación de escritorio."

689
addons/web/po/it.po Normal file
View File

@ -0,0 +1,689 @@
# Italian translation for openerp-web
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openerp-web package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-10-07 10:38+0200\n"
"PO-Revision-Date: 2011-10-08 13:39+0000\n"
"Last-Translator: Nicola Riolini - Micronaet <Unknown>\n"
"Language-Team: Italian <it@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-10-09 05:22+0000\n"
"X-Generator: Launchpad (build 14110)\n"
#: addons/web/static/src/js/view_form.js:355
msgid ""
"Warning, the record has been modified, your changes will be discarded."
msgstr ""
"Attenzione, il record è stato modificato, i vostri cambiamenti verranno "
"scartati."
#: addons/web/static/src/js/view_form.js:1659
msgid "<em>   Search More...</em>"
msgstr "<em>   Cerca ancora...</em>"
#: addons/web/static/src/js/view_form.js:1672
#, python-format
msgid "<em>   Create \"<strong>%s</strong>\"</em>"
msgstr "<em>   Crea \"<strong>%s</strong>\"</em>"
#: addons/web/static/src/js/view_form.js:1678
msgid "<em>   Create and Edit...</em>"
msgstr "<em>   Crea e modifica...</em>"
#: addons/web/static/src/js/views.js:568
msgid "You must choose at least one record."
msgstr "E' necessario selezionare almeno un record."
#: addons/web/static/src/js/views.js:569
msgid "Warning"
msgstr "Attenzione"
#: addons/web/static/src/js/views.js:609
msgid "Translations"
msgstr "Traduzioni"
#: addons/web/static/src/js/views.js:614 addons/web/static/src/xml/base.xml:0
msgid "Save"
msgstr "Salva"
#: addons/web/static/src/js/views.js:615
msgid "Close"
msgstr "Chiudi"
#: addons/web/static/src/xml/base.xml:0
msgid "x"
msgstr "x"
#: addons/web/static/src/xml/base.xml:0
msgid "#{title}"
msgstr "#{title}"
#: addons/web/static/src/xml/base.xml:0
msgid "#{text}"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Powered by"
msgstr "Powered by"
#: addons/web/static/src/xml/base.xml:0
msgid "openerp.com"
msgstr "openerp.com"
#: addons/web/static/src/xml/base.xml:0
msgid "."
msgstr "."
#: addons/web/static/src/xml/base.xml:0
msgid "Loading..."
msgstr "Caricamento..."
#: addons/web/static/src/xml/base.xml:0
msgid "Create"
msgstr "Crea"
#: addons/web/static/src/xml/base.xml:0
msgid "Drop"
msgstr "Elimina"
#: addons/web/static/src/xml/base.xml:0
msgid "Backup"
msgstr "Backup"
#: addons/web/static/src/xml/base.xml:0
msgid "Restore"
msgstr "Ripristina"
#: addons/web/static/src/xml/base.xml:0
msgid "Password"
msgstr "Password"
#: addons/web/static/src/xml/base.xml:0
msgid "Back to Login"
msgstr "Ritorno al Login"
#: addons/web/static/src/xml/base.xml:0
msgid "CREATE DATABASE"
msgstr "CREA DATABASE"
#: addons/web/static/src/xml/base.xml:0
msgid "Master password:"
msgstr "Password principale"
#: addons/web/static/src/xml/base.xml:0
msgid "New database name:"
msgstr "Nome nuovo database:"
#: addons/web/static/src/xml/base.xml:0
msgid "Load Demonstration data:"
msgstr "Caricadati dimostrativi:"
#: addons/web/static/src/xml/base.xml:0
msgid "Default language:"
msgstr "Lingua predefinita:"
#: addons/web/static/src/xml/base.xml:0
msgid "Admin password:"
msgstr "Password di amministrazione:"
#: addons/web/static/src/xml/base.xml:0
msgid "Confirm password:"
msgstr "Conferma password:"
#: addons/web/static/src/xml/base.xml:0
msgid "DROP DATABASE"
msgstr "ELIMINA DATABASE"
#: addons/web/static/src/xml/base.xml:0
msgid "Database:"
msgstr "Database:"
#: addons/web/static/src/xml/base.xml:0
msgid "Master Password:"
msgstr "Password principale"
#: addons/web/static/src/xml/base.xml:0
msgid "BACKUP DATABASE"
msgstr "BACKUP DATABASE"
#: addons/web/static/src/xml/base.xml:0
msgid "RESTORE DATABASE"
msgstr "RIPRISTINA DATABASE"
#: addons/web/static/src/xml/base.xml:0
msgid "File:"
msgstr "File:"
#: addons/web/static/src/xml/base.xml:0
msgid "CHANGE MASTER PASSWORD"
msgstr "CAMBIA PASSWORD PRINCIPALE"
#: addons/web/static/src/xml/base.xml:0
msgid "New master password:"
msgstr "Nuova password principale:"
#: addons/web/static/src/xml/base.xml:0
msgid "Confirm new master password:"
msgstr "Conferma nuova password principale"
#: addons/web/static/src/xml/base.xml:0
msgid "User:"
msgstr "Utente:"
#: addons/web/static/src/xml/base.xml:0
msgid "Password:"
msgstr "Password:"
#: addons/web/static/src/xml/base.xml:0
msgid "Database"
msgstr "Database"
#: addons/web/static/src/xml/base.xml:0
msgid "Login"
msgstr "Login"
#: addons/web/static/src/xml/base.xml:0
msgid "Bad username or password"
msgstr "Username o password errati"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"We think that daily job activities can be more intuitive, efficient, "
"automated, .. and even fun."
msgstr ""
"Pensiamo che le attività quotidiane possano essere più intuitive, "
"efficienti, automatizzate...e anche più divertenti."
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP's vision to be:"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Full featured"
msgstr "Completo"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"Today's enterprise challenges are multiple. We provide one module for each "
"need."
msgstr ""
"Le esigenze odierne delle aziende sono molteplici. Noi forniamo un modulo "
"per ogni necessità."
#: addons/web/static/src/xml/base.xml:0
msgid "Open Source"
msgstr "Open Source"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"To Build a great product, we rely on the knowledge of thousands of "
"contributors."
msgstr ""
"Per creare un buon prodotto, facciamo affidamento sull'esperienza di "
"migliaia di contributori."
#: addons/web/static/src/xml/base.xml:0
msgid "User Friendly"
msgstr "User Friendly"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"In order to be productive, people need clean and easy to use interface."
msgstr ""
"Per essere produttive, le persone necessitano di interfacce semplici e "
"pulite."
#: addons/web/static/src/xml/base.xml:0
msgid "("
msgstr "("
#: addons/web/static/src/xml/base.xml:0
msgid ")"
msgstr ")"
#: addons/web/static/src/xml/base.xml:0
msgid "LOGOUT"
msgstr "LOGOUT"
#: addons/web/static/src/xml/base.xml:0
msgid "&laquo;"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "&raquo;"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "oe_secondary_menu_item"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "oe_secondary_submenu_item"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Hide this tip"
msgstr "Nascondi questo consiglio"
#: addons/web/static/src/xml/base.xml:0
msgid "Disable all tips"
msgstr "Disabilita tutti i consigli"
#: addons/web/static/src/xml/base.xml:0
msgid "View#"
msgstr "Vista à"
#: addons/web/static/src/xml/base.xml:0
msgid "Fields"
msgstr "Campi"
#: addons/web/static/src/xml/base.xml:0
msgid "View labels"
msgstr "Visualizza etichette"
#: addons/web/static/src/xml/base.xml:0
msgid "Sidebar Relates"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Field"
msgstr "Campo"
#: addons/web/static/src/xml/base.xml:0
msgid ":"
msgstr ":"
#: addons/web/static/src/xml/base.xml:0
msgid "Translate view"
msgstr "Traduci vista"
#: addons/web/static/src/xml/base.xml:0
msgid "Translate sidebar"
msgstr "Traduci barra laterale"
#: addons/web/static/src/xml/base.xml:0
msgid "Delete"
msgstr "Elimina"
#: addons/web/static/src/xml/base.xml:0
msgid "First"
msgstr "Primo"
#: addons/web/static/src/xml/base.xml:0
msgid "<"
msgstr "<"
#: addons/web/static/src/xml/base.xml:0
msgid ">"
msgstr ">"
#: addons/web/static/src/xml/base.xml:0
msgid "Last"
msgstr "Ultimo"
#: addons/web/static/src/xml/base.xml:0
msgid "♻"
msgstr "♻"
#: addons/web/static/src/xml/base.xml:0
msgid "Save & Edit"
msgstr "Salva & Modifica"
#: addons/web/static/src/xml/base.xml:0
msgid "Create & Edit"
msgstr "Crea & Modifica"
#: addons/web/static/src/xml/base.xml:0
msgid "New"
msgstr "Nuovo"
#: addons/web/static/src/xml/base.xml:0
msgid "Duplicate"
msgstr "Duplica"
#: addons/web/static/src/xml/base.xml:0
msgid "Readonly/Editable"
msgstr "Sola lettura / Modificabile"
#: addons/web/static/src/xml/base.xml:0
msgid "<<"
msgstr "<<"
#: addons/web/static/src/xml/base.xml:0
msgid "0"
msgstr "0"
#: addons/web/static/src/xml/base.xml:0
msgid "/"
msgstr "/"
#: addons/web/static/src/xml/base.xml:0
msgid ">>"
msgstr ">>"
#: addons/web/static/src/xml/base.xml:0
msgid "Add"
msgstr "Aggiungi"
#: addons/web/static/src/xml/base.xml:0
msgid "Unhandled widget"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "?"
msgstr "?"
#: addons/web/static/src/xml/base.xml:0
msgid "#"
msgstr "#"
#: addons/web/static/src/xml/base.xml:0
msgid "Done"
msgstr "Completato"
#: addons/web/static/src/xml/base.xml:0
msgid "Open..."
msgstr "Apri..."
#: addons/web/static/src/xml/base.xml:0
msgid "Create..."
msgstr "Crea..."
#: addons/web/static/src/xml/base.xml:0
msgid "Search..."
msgstr "Cerca..."
#: addons/web/static/src/xml/base.xml:0
msgid "..."
msgstr "..."
#: addons/web/static/src/xml/base.xml:0
msgid "Uploading ..."
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Select"
msgstr "Seleziona"
#: addons/web/static/src/xml/base.xml:0
msgid "Save As"
msgstr "Salva come"
#: addons/web/static/src/xml/base.xml:0
msgid "Clear"
msgstr "Pulisci"
#: addons/web/static/src/xml/base.xml:0
msgid "Advanced Filter"
msgstr "Filtro avanzato"
#: addons/web/static/src/xml/base.xml:0
msgid "-- Filters --"
msgstr "-- Filtri --"
#: addons/web/static/src/xml/base.xml:0
msgid "-- Actions --"
msgstr "-- Azioni --"
#: addons/web/static/src/xml/base.xml:0
msgid "Save Filter"
msgstr "Salva Filtro"
#: addons/web/static/src/xml/base.xml:0
msgid "Manage Filters"
msgstr "Gestisci Filtri"
#: addons/web/static/src/xml/base.xml:0
msgid "Filter Name:"
msgstr "Nome filtro:"
#: addons/web/static/src/xml/base.xml:0
msgid "(Any existing filter with the same name will be replaced)"
msgstr "(Eventuali filtri esistenti con lo stesso nome saranno rimpiazzati)"
#: addons/web/static/src/xml/base.xml:0
msgid "Any of the following conditions must match"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "All the following conditions must match"
msgstr "Tutte le seguenti condizioni deve verificarsi"
#: addons/web/static/src/xml/base.xml:0
msgid "None of the following conditions must match"
msgstr "Nessuna delle seguenti condizioni deve verificarsi"
#: addons/web/static/src/xml/base.xml:0
msgid "Add condition"
msgstr "Aggiungi condizione"
#: addons/web/static/src/xml/base.xml:0
msgid "and"
msgstr "e"
#: addons/web/static/src/xml/base.xml:0
msgid "Cancel"
msgstr "Annulla"
#: addons/web/static/src/xml/base.xml:0
msgid "Save & New"
msgstr "Salva & Nuovo"
#: addons/web/static/src/xml/base.xml:0
msgid "Save & Close"
msgstr "Salva & Chiudi"
#: addons/web/static/src/xml/base.xml:0
msgid "Export"
msgstr "Esporta"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"This wizard will export all data that matches the current search criteria to "
"a CSV file.\n"
" You can export all data or only the fields that can be "
"reimported after modification."
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Export Type:"
msgstr "Tipo di esportazione:"
#: addons/web/static/src/xml/base.xml:0
msgid "Import Compatible Export"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Export all Data"
msgstr "Esporta tutti i dati"
#: addons/web/static/src/xml/base.xml:0
msgid "Export Formats"
msgstr "Formati esportazione"
#: addons/web/static/src/xml/base.xml:0
msgid "Available fields"
msgstr "Campi disponibili"
#: addons/web/static/src/xml/base.xml:0
msgid "Fields to export"
msgstr "Campi da esportare"
#: addons/web/static/src/xml/base.xml:0
msgid "Save fields list"
msgstr "Salva l'elenco dei campi"
#: addons/web/static/src/xml/base.xml:0
msgid "Remove"
msgstr "Rimuovi"
#: addons/web/static/src/xml/base.xml:0
msgid "Remove All"
msgstr "Rimuovi tutto"
#: addons/web/static/src/xml/base.xml:0
msgid "Name"
msgstr "Nome"
#: addons/web/static/src/xml/base.xml:0
msgid "&nbsp;"
msgstr "&nbsp;"
#: addons/web/static/src/xml/base.xml:0
msgid "Save as:"
msgstr "Salva come:"
#: addons/web/static/src/xml/base.xml:0
msgid "Ok"
msgstr "Ok"
#: addons/web/static/src/xml/base.xml:0
msgid "Saved exports:"
msgstr "Esportazioni salvate:"
#: addons/web/static/src/xml/base.xml:0
msgid "Old Password:"
msgstr "Vecchia Password:"
#: addons/web/static/src/xml/base.xml:0
msgid "New Password:"
msgstr "Nuova password:"
#: addons/web/static/src/xml/base.xml:0
msgid "Confirm Password:"
msgstr "Conferma password:"
#: addons/web/static/src/xml/base.xml:0
msgid "Import"
msgstr "Importa"
#: addons/web/static/src/xml/base.xml:0
msgid "1. Import a .CSV file"
msgstr "1. Importa un file .CSV"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"Select a .CSV file to import. If you need a sample of file to import,\n"
" you should use the export tool with the \"Import Compatible\" option."
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "CSV File:"
msgstr "File CSV:"
#: addons/web/static/src/xml/base.xml:0
msgid "2. Check your file format"
msgstr "2. Controlla il formato del tuo file"
#: addons/web/static/src/xml/base.xml:0
msgid "Import Options"
msgstr "Opzioni di importazione"
#: addons/web/static/src/xml/base.xml:0
msgid "Does your file have titles?"
msgstr "Il vostro file ha i titoli?"
#: addons/web/static/src/xml/base.xml:0
msgid "Separator:"
msgstr "Separatore:"
#: addons/web/static/src/xml/base.xml:0
msgid "Delimiter:"
msgstr "Delimitatore:"
#: addons/web/static/src/xml/base.xml:0
msgid "Encoding:"
msgstr "Codifica:"
#: addons/web/static/src/xml/base.xml:0
msgid "UTF-8"
msgstr "UTF-8"
#: addons/web/static/src/xml/base.xml:0
msgid "Latin 1"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Lines to skip"
msgstr "Linee da saltare"
#: addons/web/static/src/xml/base.xml:0
msgid "The import failed due to:"
msgstr "L'importazione è fallita a causa di:"
#: addons/web/static/src/xml/base.xml:0
msgid "Here is a preview of the file we could not import:"
msgstr "Ecco un anteprima del file che non si è riuscito ad importare:"
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP Web"
msgstr "OpenERP Web"
#: addons/web/static/src/xml/base.xml:0
msgid "Version"
msgstr "Versione"
#: addons/web/static/src/xml/base.xml:0
msgid "Copyright © 2011-TODAY OpenERP SA. All Rights Reserved."
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP is a trademark of the"
msgstr "OpenERP è un marchio di"
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP SA Company"
msgstr "OpenERP SA Company"
#: addons/web/static/src/xml/base.xml:0
msgid "Licenced under the terms of"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "GNU Affero General Public License"
msgstr "GNU Affero General Public License"
#: addons/web/static/src/xml/base.xml:0
msgid "About OpenERP"
msgstr "Informazioni su OpenERP"
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP"
msgstr "OpenERP"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"is a free enterprise-scale software system that is designed to boost\n"
" productivity and profit through data integration. It connects, "
"improves and\n"
" manages business processes in areas such as sales, finance, "
"supply chain,\n"
" project management, production, services, CRM, etc..."
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid ""
"The system is platform-independent, and can be installed on Windows, Mac OS "
"X,\n"
" and various Linux and other Unix-based distributions. Its "
"architecture enables\n"
" new functionality to be rapidly created, modifications to be "
"made to a\n"
" production system and migration to a new version to be "
"straightforward."
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid ""
"Depending on your needs, OpenERP is available through a web or application "
"client."
msgstr ""
"In base alle tue esigenze, OpenERP è disponibile tramite un browse web o "
"un'applicazione client."

689
addons/web/po/nl_BE.po Normal file
View File

@ -0,0 +1,689 @@
# Dutch (Belgium) translation for openerp-web
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openerp-web package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-10-07 10:38+0200\n"
"PO-Revision-Date: 2011-10-07 12:50+0000\n"
"Last-Translator: Niels Huylebroeck <Unknown>\n"
"Language-Team: Dutch (Belgium) <nl_BE@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-10-08 05:29+0000\n"
"X-Generator: Launchpad (build 14110)\n"
#: addons/web/static/src/js/view_form.js:355
msgid ""
"Warning, the record has been modified, your changes will be discarded."
msgstr ""
"Opgelet, het record werd gewijzigd, uw veranderingen zullen niet opgeslagen "
"worden."
#: addons/web/static/src/js/view_form.js:1659
msgid "<em>   Search More...</em>"
msgstr "<em>   Uitgebreid zoeken...</em>"
#: addons/web/static/src/js/view_form.js:1672
#, python-format
msgid "<em>   Create \"<strong>%s</strong>\"</em>"
msgstr "<em>   Creër \"<strong>%s</strong>\"</em>"
#: addons/web/static/src/js/view_form.js:1678
msgid "<em>   Create and Edit...</em>"
msgstr "<em>   Creër en bewerk...</em>"
#: addons/web/static/src/js/views.js:568
msgid "You must choose at least one record."
msgstr "U moet minstens een record selecteren."
#: addons/web/static/src/js/views.js:569
msgid "Warning"
msgstr "Waarschuwing"
#: addons/web/static/src/js/views.js:609
msgid "Translations"
msgstr "Vertalingen"
#: addons/web/static/src/js/views.js:614 addons/web/static/src/xml/base.xml:0
msgid "Save"
msgstr "Opslaan"
#: addons/web/static/src/js/views.js:615
msgid "Close"
msgstr "Sluiten"
#: addons/web/static/src/xml/base.xml:0
msgid "x"
msgstr "x"
#: addons/web/static/src/xml/base.xml:0
msgid "#{title}"
msgstr "#{title}"
#: addons/web/static/src/xml/base.xml:0
msgid "#{text}"
msgstr "#{text}"
#: addons/web/static/src/xml/base.xml:0
msgid "Powered by"
msgstr "Mogelijk gemaakt door"
#: addons/web/static/src/xml/base.xml:0
msgid "openerp.com"
msgstr "openerp.com"
#: addons/web/static/src/xml/base.xml:0
msgid "."
msgstr "."
#: addons/web/static/src/xml/base.xml:0
msgid "Loading..."
msgstr "Laden..."
#: addons/web/static/src/xml/base.xml:0
msgid "Create"
msgstr "Creër"
#: addons/web/static/src/xml/base.xml:0
msgid "Drop"
msgstr "Drop"
#: addons/web/static/src/xml/base.xml:0
msgid "Backup"
msgstr "Backup"
#: addons/web/static/src/xml/base.xml:0
msgid "Restore"
msgstr "Restore"
#: addons/web/static/src/xml/base.xml:0
msgid "Password"
msgstr "Wachtwoord"
#: addons/web/static/src/xml/base.xml:0
msgid "Back to Login"
msgstr "Terug naar aanmelding"
#: addons/web/static/src/xml/base.xml:0
msgid "CREATE DATABASE"
msgstr "CREATE DATABASE"
#: addons/web/static/src/xml/base.xml:0
msgid "Master password:"
msgstr "Master wachtwoord:"
#: addons/web/static/src/xml/base.xml:0
msgid "New database name:"
msgstr "Nieuwe database naam:"
#: addons/web/static/src/xml/base.xml:0
msgid "Load Demonstration data:"
msgstr "Demonstratie data laden:"
#: addons/web/static/src/xml/base.xml:0
msgid "Default language:"
msgstr "Standaard taal:"
#: addons/web/static/src/xml/base.xml:0
msgid "Admin password:"
msgstr "Beheerder wachtwoord:"
#: addons/web/static/src/xml/base.xml:0
msgid "Confirm password:"
msgstr "Bevestig wachtwoord:"
#: addons/web/static/src/xml/base.xml:0
msgid "DROP DATABASE"
msgstr "DROP DATABASE"
#: addons/web/static/src/xml/base.xml:0
msgid "Database:"
msgstr "Database:"
#: addons/web/static/src/xml/base.xml:0
msgid "Master Password:"
msgstr "Master wachtwoord:"
#: addons/web/static/src/xml/base.xml:0
msgid "BACKUP DATABASE"
msgstr "BACKUP DATABASE"
#: addons/web/static/src/xml/base.xml:0
msgid "RESTORE DATABASE"
msgstr "RESTORE DATABASE"
#: addons/web/static/src/xml/base.xml:0
msgid "File:"
msgstr "Bestand:"
#: addons/web/static/src/xml/base.xml:0
msgid "CHANGE MASTER PASSWORD"
msgstr "CHANGE MASTER PASSWORD"
#: addons/web/static/src/xml/base.xml:0
msgid "New master password:"
msgstr "Nieuw master wachtwoord:"
#: addons/web/static/src/xml/base.xml:0
msgid "Confirm new master password:"
msgstr "Bevestig nieuw master wachtwoord:"
#: addons/web/static/src/xml/base.xml:0
msgid "User:"
msgstr "Gebruiker:"
#: addons/web/static/src/xml/base.xml:0
msgid "Password:"
msgstr "Wachtwoord:"
#: addons/web/static/src/xml/base.xml:0
msgid "Database"
msgstr "Database"
#: addons/web/static/src/xml/base.xml:0
msgid "Login"
msgstr "Login"
#: addons/web/static/src/xml/base.xml:0
msgid "Bad username or password"
msgstr "Verkeerde gebruikersnaam of wachtwoord"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"We think that daily job activities can be more intuitive, efficient, "
"automated, .. and even fun."
msgstr ""
"Wij geloven dat je dagelijkse werk intuitiver, efficienter, geautomatiseerd "
"en leuker kan zijn."
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP's vision to be:"
msgstr "OpenERP's visie is:"
#: addons/web/static/src/xml/base.xml:0
msgid "Full featured"
msgstr "Volledig uitgerust"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"Today's enterprise challenges are multiple. We provide one module for each "
"need."
msgstr ""
"Hedendaagse uitdaging voor bedrijven zijn alom. Wij voorzien een module voor "
"elke uitdaging."
#: addons/web/static/src/xml/base.xml:0
msgid "Open Source"
msgstr "Open Source"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"To Build a great product, we rely on the knowledge of thousands of "
"contributors."
msgstr ""
"Om een geweldig product te maken vertrouwen we op de kennis van duizenden "
"mensen."
#: addons/web/static/src/xml/base.xml:0
msgid "User Friendly"
msgstr "Gebruiksvriendelijk"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"In order to be productive, people need clean and easy to use interface."
msgstr ""
"Om productief te kunnen zijn hebben mensen een mooie en gemakkelijke "
"interface nodig."
#: addons/web/static/src/xml/base.xml:0
msgid "("
msgstr "("
#: addons/web/static/src/xml/base.xml:0
msgid ")"
msgstr ")"
#: addons/web/static/src/xml/base.xml:0
msgid "LOGOUT"
msgstr "LOGOUT"
#: addons/web/static/src/xml/base.xml:0
msgid "&laquo;"
msgstr "&laquo;"
#: addons/web/static/src/xml/base.xml:0
msgid "&raquo;"
msgstr "&raquo;"
#: addons/web/static/src/xml/base.xml:0
msgid "oe_secondary_menu_item"
msgstr "oe_secondary_menu_item"
#: addons/web/static/src/xml/base.xml:0
msgid "oe_secondary_submenu_item"
msgstr "oe_secondary_submenu_item"
#: addons/web/static/src/xml/base.xml:0
msgid "Hide this tip"
msgstr "Verberg deze tip"
#: addons/web/static/src/xml/base.xml:0
msgid "Disable all tips"
msgstr "Verberg alle tips"
#: addons/web/static/src/xml/base.xml:0
msgid "View#"
msgstr "View#"
#: addons/web/static/src/xml/base.xml:0
msgid "Fields"
msgstr "Velden"
#: addons/web/static/src/xml/base.xml:0
msgid "View labels"
msgstr "Toon labels"
#: addons/web/static/src/xml/base.xml:0
msgid "Sidebar Relates"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Field"
msgstr "Veld"
#: addons/web/static/src/xml/base.xml:0
msgid ":"
msgstr ":"
#: addons/web/static/src/xml/base.xml:0
msgid "Translate view"
msgstr "Vertaal scherm"
#: addons/web/static/src/xml/base.xml:0
msgid "Translate sidebar"
msgstr "Vertaal balk"
#: addons/web/static/src/xml/base.xml:0
msgid "Delete"
msgstr "Verwijder"
#: addons/web/static/src/xml/base.xml:0
msgid "First"
msgstr "Eerste"
#: addons/web/static/src/xml/base.xml:0
msgid "<"
msgstr "<"
#: addons/web/static/src/xml/base.xml:0
msgid ">"
msgstr ">"
#: addons/web/static/src/xml/base.xml:0
msgid "Last"
msgstr "Laatste"
#: addons/web/static/src/xml/base.xml:0
msgid "♻"
msgstr "♻"
#: addons/web/static/src/xml/base.xml:0
msgid "Save & Edit"
msgstr "Opslaan & Bewerken"
#: addons/web/static/src/xml/base.xml:0
msgid "Create & Edit"
msgstr "Creër & Bewerk"
#: addons/web/static/src/xml/base.xml:0
msgid "New"
msgstr "Nieuw"
#: addons/web/static/src/xml/base.xml:0
msgid "Duplicate"
msgstr "Dupliceer"
#: addons/web/static/src/xml/base.xml:0
msgid "Readonly/Editable"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "<<"
msgstr "<<"
#: addons/web/static/src/xml/base.xml:0
msgid "0"
msgstr "0"
#: addons/web/static/src/xml/base.xml:0
msgid "/"
msgstr "/"
#: addons/web/static/src/xml/base.xml:0
msgid ">>"
msgstr ">>"
#: addons/web/static/src/xml/base.xml:0
msgid "Add"
msgstr "Toevoegen"
#: addons/web/static/src/xml/base.xml:0
msgid "Unhandled widget"
msgstr "Niet-verwerkbare widget"
#: addons/web/static/src/xml/base.xml:0
msgid "?"
msgstr "?"
#: addons/web/static/src/xml/base.xml:0
msgid "#"
msgstr "#"
#: addons/web/static/src/xml/base.xml:0
msgid "Done"
msgstr "Voltooid"
#: addons/web/static/src/xml/base.xml:0
msgid "Open..."
msgstr "Open..."
#: addons/web/static/src/xml/base.xml:0
msgid "Create..."
msgstr "Creër..."
#: addons/web/static/src/xml/base.xml:0
msgid "Search..."
msgstr "Zoeken..."
#: addons/web/static/src/xml/base.xml:0
msgid "..."
msgstr "..."
#: addons/web/static/src/xml/base.xml:0
msgid "Uploading ..."
msgstr "Uploaden ..."
#: addons/web/static/src/xml/base.xml:0
msgid "Select"
msgstr "Selecteer"
#: addons/web/static/src/xml/base.xml:0
msgid "Save As"
msgstr "Opslaan als"
#: addons/web/static/src/xml/base.xml:0
msgid "Clear"
msgstr "Leegmaken"
#: addons/web/static/src/xml/base.xml:0
msgid "Advanced Filter"
msgstr "Geavanceerde filter"
#: addons/web/static/src/xml/base.xml:0
msgid "-- Filters --"
msgstr "-- Filters --"
#: addons/web/static/src/xml/base.xml:0
msgid "-- Actions --"
msgstr "-- Acties --"
#: addons/web/static/src/xml/base.xml:0
msgid "Save Filter"
msgstr "Filter opslaan"
#: addons/web/static/src/xml/base.xml:0
msgid "Manage Filters"
msgstr "Filters beheren"
#: addons/web/static/src/xml/base.xml:0
msgid "Filter Name:"
msgstr "Filternaam:"
#: addons/web/static/src/xml/base.xml:0
msgid "(Any existing filter with the same name will be replaced)"
msgstr "(Bestaande filters met dezelfde naam worden overschreven)"
#: addons/web/static/src/xml/base.xml:0
msgid "Any of the following conditions must match"
msgstr "Een van de volgende voorwaarden moet overeenstemmen"
#: addons/web/static/src/xml/base.xml:0
msgid "All the following conditions must match"
msgstr "Elke van de volgende voorwaarden moeten overeenstemmen"
#: addons/web/static/src/xml/base.xml:0
msgid "None of the following conditions must match"
msgstr "Geen enkele van de volgende voorwaarden moeten overeenstemmen"
#: addons/web/static/src/xml/base.xml:0
msgid "Add condition"
msgstr "Voorwaarde toevoegen"
#: addons/web/static/src/xml/base.xml:0
msgid "and"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Cancel"
msgstr "Annuleren"
#: addons/web/static/src/xml/base.xml:0
msgid "Save & New"
msgstr "Opslaan & Nieuwe"
#: addons/web/static/src/xml/base.xml:0
msgid "Save & Close"
msgstr "Opslaan & Sluiten"
#: addons/web/static/src/xml/base.xml:0
msgid "Export"
msgstr "Exporteren"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"This wizard will export all data that matches the current search criteria to "
"a CSV file.\n"
" You can export all data or only the fields that can be "
"reimported after modification."
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Export Type:"
msgstr "Export Type:"
#: addons/web/static/src/xml/base.xml:0
msgid "Import Compatible Export"
msgstr "Exporteren op een compatibele manier"
#: addons/web/static/src/xml/base.xml:0
msgid "Export all Data"
msgstr "Alles exporteren"
#: addons/web/static/src/xml/base.xml:0
msgid "Export Formats"
msgstr "Export formaten"
#: addons/web/static/src/xml/base.xml:0
msgid "Available fields"
msgstr "Beschikbare velden"
#: addons/web/static/src/xml/base.xml:0
msgid "Fields to export"
msgstr "Te exporteren velden"
#: addons/web/static/src/xml/base.xml:0
msgid "Save fields list"
msgstr "Export definitie opslaan"
#: addons/web/static/src/xml/base.xml:0
msgid "Remove"
msgstr "Verwijderen"
#: addons/web/static/src/xml/base.xml:0
msgid "Remove All"
msgstr "Alles verwijderen"
#: addons/web/static/src/xml/base.xml:0
msgid "Name"
msgstr "Naam"
#: addons/web/static/src/xml/base.xml:0
msgid "&nbsp;"
msgstr "&nbsp;"
#: addons/web/static/src/xml/base.xml:0
msgid "Save as:"
msgstr "Opslaan als:"
#: addons/web/static/src/xml/base.xml:0
msgid "Ok"
msgstr "Ok"
#: addons/web/static/src/xml/base.xml:0
msgid "Saved exports:"
msgstr "Export definities"
#: addons/web/static/src/xml/base.xml:0
msgid "Old Password:"
msgstr "Huidig wachtwoord:"
#: addons/web/static/src/xml/base.xml:0
msgid "New Password:"
msgstr "Nieuw wachtwoord:"
#: addons/web/static/src/xml/base.xml:0
msgid "Confirm Password:"
msgstr "Bevestig wachtwoord:"
#: addons/web/static/src/xml/base.xml:0
msgid "Import"
msgstr "Importeren"
#: addons/web/static/src/xml/base.xml:0
msgid "1. Import a .CSV file"
msgstr "1. Importeer een .CSV bestand"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"Select a .CSV file to import. If you need a sample of file to import,\n"
" you should use the export tool with the \"Import Compatible\" option."
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "CSV File:"
msgstr "CSV Bestand:"
#: addons/web/static/src/xml/base.xml:0
msgid "2. Check your file format"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Import Options"
msgstr "Import opties"
#: addons/web/static/src/xml/base.xml:0
msgid "Does your file have titles?"
msgstr "Heeft uw bestand een hoofding ?"
#: addons/web/static/src/xml/base.xml:0
msgid "Separator:"
msgstr "Scheidingsteken"
#: addons/web/static/src/xml/base.xml:0
msgid "Delimiter:"
msgstr "Veld begrenzing"
#: addons/web/static/src/xml/base.xml:0
msgid "Encoding:"
msgstr "Encodering:"
#: addons/web/static/src/xml/base.xml:0
msgid "UTF-8"
msgstr "UTF-8"
#: addons/web/static/src/xml/base.xml:0
msgid "Latin 1"
msgstr "Latin 1"
#: addons/web/static/src/xml/base.xml:0
msgid "Lines to skip"
msgstr "Aantal lijnen overslaan"
#: addons/web/static/src/xml/base.xml:0
msgid "The import failed due to:"
msgstr "De import is niet gelukt omdat:"
#: addons/web/static/src/xml/base.xml:0
msgid "Here is a preview of the file we could not import:"
msgstr "Hier is een voorbeeld van het bestand dat we niet konden importeren:"
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP Web"
msgstr "OpenERP Web"
#: addons/web/static/src/xml/base.xml:0
msgid "Version"
msgstr "Versie"
#: addons/web/static/src/xml/base.xml:0
msgid "Copyright © 2011-TODAY OpenERP SA. All Rights Reserved."
msgstr "Copyright © 2011-TODAY OpenERP SA. Alle rechten voorbehouden."
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP is a trademark of the"
msgstr "OpenERP is een handelsmerk van"
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP SA Company"
msgstr "OpenERP SA Company"
#: addons/web/static/src/xml/base.xml:0
msgid "Licenced under the terms of"
msgstr "Gelicensieërd onder de voorwaarden van"
#: addons/web/static/src/xml/base.xml:0
msgid "GNU Affero General Public License"
msgstr "GNU Affero General Public License"
#: addons/web/static/src/xml/base.xml:0
msgid "About OpenERP"
msgstr "About OpenERP"
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP"
msgstr "OpenERP"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"is a free enterprise-scale software system that is designed to boost\n"
" productivity and profit through data integration. It connects, "
"improves and\n"
" manages business processes in areas such as sales, finance, "
"supply chain,\n"
" project management, production, services, CRM, etc..."
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid ""
"The system is platform-independent, and can be installed on Windows, Mac OS "
"X,\n"
" and various Linux and other Unix-based distributions. Its "
"architecture enables\n"
" new functionality to be rapidly created, modifications to be "
"made to a\n"
" production system and migration to a new version to be "
"straightforward."
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid ""
"Depending on your needs, OpenERP is available through a web or application "
"client."
msgstr ""
"Afhankelijk van uw behoefte is OpenERP beschikbaar via een web- of desktop-"
"applicatie."

707
addons/web/po/sl.po Normal file
View File

@ -0,0 +1,707 @@
# Slovenian translation for openerp-web
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openerp-web package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-10-07 10:38+0200\n"
"PO-Revision-Date: 2011-10-19 07:07+0000\n"
"Last-Translator: Anze (Neotek) <Unknown>\n"
"Language-Team: Slovenian <sl@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-10-20 04:48+0000\n"
"X-Generator: Launchpad (build 14165)\n"
#: addons/web/static/src/js/view_form.js:355
msgid ""
"Warning, the record has been modified, your changes will be discarded."
msgstr ""
"Opozorilo, zapis je bil spremenjen, zato bodo vaše spremembe zavržene."
#: addons/web/static/src/js/view_form.js:1659
msgid "<em>   Search More...</em>"
msgstr "<em>   Iskanje več...</em>"
#: addons/web/static/src/js/view_form.js:1672
#, python-format
msgid "<em>   Create \"<strong>%s</strong>\"</em>"
msgstr "<em>   Ustvari \"<strong>%s</strong>\"</em>"
#: addons/web/static/src/js/view_form.js:1678
msgid "<em>   Create and Edit...</em>"
msgstr "<em>   Ustvari in uredi...</em>"
#: addons/web/static/src/js/views.js:568
msgid "You must choose at least one record."
msgstr "Izbrati morate vsaj en zapis."
#: addons/web/static/src/js/views.js:569
msgid "Warning"
msgstr "Opozorilo"
#: addons/web/static/src/js/views.js:609
msgid "Translations"
msgstr "Prevodi"
#: addons/web/static/src/js/views.js:614 addons/web/static/src/xml/base.xml:0
msgid "Save"
msgstr "Shrani"
#: addons/web/static/src/js/views.js:615
msgid "Close"
msgstr "Zapri"
#: addons/web/static/src/xml/base.xml:0
msgid "x"
msgstr "x"
#: addons/web/static/src/xml/base.xml:0
msgid "#{title}"
msgstr "#{title}"
#: addons/web/static/src/xml/base.xml:0
msgid "#{text}"
msgstr "#{text}"
#: addons/web/static/src/xml/base.xml:0
msgid "Powered by"
msgstr "Poganja ga"
#: addons/web/static/src/xml/base.xml:0
msgid "openerp.com"
msgstr "openerp.com"
#: addons/web/static/src/xml/base.xml:0
msgid "."
msgstr "."
#: addons/web/static/src/xml/base.xml:0
msgid "Loading..."
msgstr "Nalaganje …"
#: addons/web/static/src/xml/base.xml:0
msgid "Create"
msgstr "Ustvari"
#: addons/web/static/src/xml/base.xml:0
msgid "Drop"
msgstr "Izbriši"
#: addons/web/static/src/xml/base.xml:0
msgid "Backup"
msgstr "Varnostna kopija"
#: addons/web/static/src/xml/base.xml:0
msgid "Restore"
msgstr "Obnovi"
#: addons/web/static/src/xml/base.xml:0
msgid "Password"
msgstr "Geslo"
#: addons/web/static/src/xml/base.xml:0
msgid "Back to Login"
msgstr "Nazaj na prijavo"
#: addons/web/static/src/xml/base.xml:0
msgid "CREATE DATABASE"
msgstr "USTVARI PODATKOVNO BAZO"
#: addons/web/static/src/xml/base.xml:0
msgid "Master password:"
msgstr "Glavno geslo:"
#: addons/web/static/src/xml/base.xml:0
msgid "New database name:"
msgstr "Ime nove podatkovne baze"
#: addons/web/static/src/xml/base.xml:0
msgid "Load Demonstration data:"
msgstr "Naloži demonstracijske podatke:"
#: addons/web/static/src/xml/base.xml:0
msgid "Default language:"
msgstr "Privzeti jezik:"
#: addons/web/static/src/xml/base.xml:0
msgid "Admin password:"
msgstr "Admin geslo:"
#: addons/web/static/src/xml/base.xml:0
msgid "Confirm password:"
msgstr "Potrdite geslo"
#: addons/web/static/src/xml/base.xml:0
msgid "DROP DATABASE"
msgstr "IZBRIŠI PODATKOVNO BAZO"
#: addons/web/static/src/xml/base.xml:0
msgid "Database:"
msgstr "Podatkovna baza"
#: addons/web/static/src/xml/base.xml:0
msgid "Master Password:"
msgstr "Glavno geslo:"
#: addons/web/static/src/xml/base.xml:0
msgid "BACKUP DATABASE"
msgstr "VARNOSTNA KOPIJA PODATKOVNE BAZE"
#: addons/web/static/src/xml/base.xml:0
msgid "RESTORE DATABASE"
msgstr "OBNOVITEV PODATKOVNE BAZE"
#: addons/web/static/src/xml/base.xml:0
msgid "File:"
msgstr "Datoteka:"
#: addons/web/static/src/xml/base.xml:0
msgid "CHANGE MASTER PASSWORD"
msgstr "SPREMENI GLAVNO GELSO"
#: addons/web/static/src/xml/base.xml:0
msgid "New master password:"
msgstr "Novo glavno geslo:"
#: addons/web/static/src/xml/base.xml:0
msgid "Confirm new master password:"
msgstr "Potrdi novo glavno geslo:"
#: addons/web/static/src/xml/base.xml:0
msgid "User:"
msgstr "Uporabnik:"
#: addons/web/static/src/xml/base.xml:0
msgid "Password:"
msgstr "Geslo:"
#: addons/web/static/src/xml/base.xml:0
msgid "Database"
msgstr "Podatkovna baza"
#: addons/web/static/src/xml/base.xml:0
msgid "Login"
msgstr "Prijava"
#: addons/web/static/src/xml/base.xml:0
msgid "Bad username or password"
msgstr "Napačno uporabniško ime ali geslo"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"We think that daily job activities can be more intuitive, efficient, "
"automated, .. and even fun."
msgstr ""
"Menimo, da so lahko dnevne dejavnosti dela bolj intuitivna, učinkovita, "
"avtomatska, .. in celo zabavna."
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP's vision to be:"
msgstr "Vizija OpenERP je:"
#: addons/web/static/src/xml/base.xml:0
msgid "Full featured"
msgstr "Oblikovno popoln"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"Today's enterprise challenges are multiple. We provide one module for each "
"need."
msgstr ""
"Današnja podjetja imajo več izzivov. Nudimo en modul za vsako potrebo."
#: addons/web/static/src/xml/base.xml:0
msgid "Open Source"
msgstr "Odprta koda"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"To Build a great product, we rely on the knowledge of thousands of "
"contributors."
msgstr ""
"Za zgraditev odličnega izdeleka, se zanašamo na znanje tisočih sodelavcev."
#: addons/web/static/src/xml/base.xml:0
msgid "User Friendly"
msgstr "Prijazen do uporabnika"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"In order to be productive, people need clean and easy to use interface."
msgstr ""
"Da bi bili produktivni, ljudje potrebujejo čist in enostaven za uporabniški "
"vmesnik."
#: addons/web/static/src/xml/base.xml:0
msgid "("
msgstr "("
#: addons/web/static/src/xml/base.xml:0
msgid ")"
msgstr ")"
#: addons/web/static/src/xml/base.xml:0
msgid "LOGOUT"
msgstr "ODJAVA"
#: addons/web/static/src/xml/base.xml:0
msgid "&laquo;"
msgstr "&laquo;"
#: addons/web/static/src/xml/base.xml:0
msgid "&raquo;"
msgstr "&raquo;"
#: addons/web/static/src/xml/base.xml:0
msgid "oe_secondary_menu_item"
msgstr "oe_secondary_menu_item"
#: addons/web/static/src/xml/base.xml:0
msgid "oe_secondary_submenu_item"
msgstr "oe_secondary_submenu_item"
#: addons/web/static/src/xml/base.xml:0
msgid "Hide this tip"
msgstr "Skrij ta namig"
#: addons/web/static/src/xml/base.xml:0
msgid "Disable all tips"
msgstr "Onemogoči vse namige"
#: addons/web/static/src/xml/base.xml:0
msgid "View#"
msgstr "Ogled#"
#: addons/web/static/src/xml/base.xml:0
msgid "Fields"
msgstr "Polja"
#: addons/web/static/src/xml/base.xml:0
msgid "View labels"
msgstr "Ogled oznak"
#: addons/web/static/src/xml/base.xml:0
msgid "Sidebar Relates"
msgstr "Sorodne stranske vrstice"
#: addons/web/static/src/xml/base.xml:0
msgid "Field"
msgstr "Polje"
#: addons/web/static/src/xml/base.xml:0
msgid ":"
msgstr ":"
#: addons/web/static/src/xml/base.xml:0
msgid "Translate view"
msgstr "Preveden pogled"
#: addons/web/static/src/xml/base.xml:0
msgid "Translate sidebar"
msgstr "Prevedi stransko vrstico"
#: addons/web/static/src/xml/base.xml:0
msgid "Delete"
msgstr "Izbriši"
#: addons/web/static/src/xml/base.xml:0
msgid "First"
msgstr "Začetek"
#: addons/web/static/src/xml/base.xml:0
msgid "<"
msgstr "<"
#: addons/web/static/src/xml/base.xml:0
msgid ">"
msgstr ">"
#: addons/web/static/src/xml/base.xml:0
msgid "Last"
msgstr "Konec"
#: addons/web/static/src/xml/base.xml:0
msgid "♻"
msgstr "♻"
#: addons/web/static/src/xml/base.xml:0
msgid "Save & Edit"
msgstr "Shrani & Uredi"
#: addons/web/static/src/xml/base.xml:0
msgid "Create & Edit"
msgstr "Ustvari & Uredi"
#: addons/web/static/src/xml/base.xml:0
msgid "New"
msgstr "Novo"
#: addons/web/static/src/xml/base.xml:0
msgid "Duplicate"
msgstr "Podvoji"
#: addons/web/static/src/xml/base.xml:0
msgid "Readonly/Editable"
msgstr "Samo za branje/možno urejanje"
#: addons/web/static/src/xml/base.xml:0
msgid "<<"
msgstr "<<"
#: addons/web/static/src/xml/base.xml:0
msgid "0"
msgstr "0"
#: addons/web/static/src/xml/base.xml:0
msgid "/"
msgstr "/"
#: addons/web/static/src/xml/base.xml:0
msgid ">>"
msgstr ">>"
#: addons/web/static/src/xml/base.xml:0
msgid "Add"
msgstr "Dodaj"
#: addons/web/static/src/xml/base.xml:0
msgid "Unhandled widget"
msgstr "Neobravnavani gradnik"
#: addons/web/static/src/xml/base.xml:0
msgid "?"
msgstr "?"
#: addons/web/static/src/xml/base.xml:0
msgid "#"
msgstr "#"
#: addons/web/static/src/xml/base.xml:0
msgid "Done"
msgstr "Končano"
#: addons/web/static/src/xml/base.xml:0
msgid "Open..."
msgstr "Odpri ..."
#: addons/web/static/src/xml/base.xml:0
msgid "Create..."
msgstr "Ustvari ..."
#: addons/web/static/src/xml/base.xml:0
msgid "Search..."
msgstr "Iskanje ..."
#: addons/web/static/src/xml/base.xml:0
msgid "..."
msgstr "..."
#: addons/web/static/src/xml/base.xml:0
msgid "Uploading ..."
msgstr "Nalaganje..."
#: addons/web/static/src/xml/base.xml:0
msgid "Select"
msgstr "Izberi"
#: addons/web/static/src/xml/base.xml:0
msgid "Save As"
msgstr "Shrani kot"
#: addons/web/static/src/xml/base.xml:0
msgid "Clear"
msgstr "Počisti"
#: addons/web/static/src/xml/base.xml:0
msgid "Advanced Filter"
msgstr "Napredni filter"
#: addons/web/static/src/xml/base.xml:0
msgid "-- Filters --"
msgstr "-- Filtr i--"
#: addons/web/static/src/xml/base.xml:0
msgid "-- Actions --"
msgstr "-- Dejanja --"
#: addons/web/static/src/xml/base.xml:0
msgid "Save Filter"
msgstr "Shrani filter"
#: addons/web/static/src/xml/base.xml:0
msgid "Manage Filters"
msgstr "Upravljanje filtrov"
#: addons/web/static/src/xml/base.xml:0
msgid "Filter Name:"
msgstr "Ime filtra:"
#: addons/web/static/src/xml/base.xml:0
msgid "(Any existing filter with the same name will be replaced)"
msgstr "(Vsak obstoječ filter z istim imenom bo zamenjan)"
#: addons/web/static/src/xml/base.xml:0
msgid "Any of the following conditions must match"
msgstr "Vsak od teh pogojev se mora ujemati"
#: addons/web/static/src/xml/base.xml:0
msgid "All the following conditions must match"
msgstr "Vsi naslednji pogoji se morajo ujemati"
#: addons/web/static/src/xml/base.xml:0
msgid "None of the following conditions must match"
msgstr "Nobena od naslednjih pogojev se morajo ujemati"
#: addons/web/static/src/xml/base.xml:0
msgid "Add condition"
msgstr "Dodaj pogoj"
#: addons/web/static/src/xml/base.xml:0
msgid "and"
msgstr "in"
#: addons/web/static/src/xml/base.xml:0
msgid "Cancel"
msgstr "Prekliči"
#: addons/web/static/src/xml/base.xml:0
msgid "Save & New"
msgstr "Shrani & Novo"
#: addons/web/static/src/xml/base.xml:0
msgid "Save & Close"
msgstr "Shrani & Zapri"
#: addons/web/static/src/xml/base.xml:0
msgid "Export"
msgstr "Izvozi"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"This wizard will export all data that matches the current search criteria to "
"a CSV file.\n"
" You can export all data or only the fields that can be "
"reimported after modification."
msgstr ""
"Ta čarovnik bo izvozil vse podatke, ki se ujemajo s trenutnim kriterijem "
"iskanja, v datoteko CSV.\n"
" Izvozite lahko vse podatke ali samo polja, ki jih je mogoče "
"ponovno uvoziti po spremembi."
#: addons/web/static/src/xml/base.xml:0
msgid "Export Type:"
msgstr "Tip izvoza:"
#: addons/web/static/src/xml/base.xml:0
msgid "Import Compatible Export"
msgstr "Uvozi kompatibilen izvoz"
#: addons/web/static/src/xml/base.xml:0
msgid "Export all Data"
msgstr "Izvozi vse podatke"
#: addons/web/static/src/xml/base.xml:0
msgid "Export Formats"
msgstr "Oblike izvoza"
#: addons/web/static/src/xml/base.xml:0
msgid "Available fields"
msgstr "Razpoložljiva polja"
#: addons/web/static/src/xml/base.xml:0
msgid "Fields to export"
msgstr "Polja za izvoz"
#: addons/web/static/src/xml/base.xml:0
msgid "Save fields list"
msgstr "Shrani seznam polj"
#: addons/web/static/src/xml/base.xml:0
msgid "Remove"
msgstr "Odstrani"
#: addons/web/static/src/xml/base.xml:0
msgid "Remove All"
msgstr "Odstrani vse"
#: addons/web/static/src/xml/base.xml:0
msgid "Name"
msgstr "Ime"
#: addons/web/static/src/xml/base.xml:0
msgid "&nbsp;"
msgstr "&nbsp;"
#: addons/web/static/src/xml/base.xml:0
msgid "Save as:"
msgstr "Shrani kot:"
#: addons/web/static/src/xml/base.xml:0
msgid "Ok"
msgstr "Vredu"
#: addons/web/static/src/xml/base.xml:0
msgid "Saved exports:"
msgstr "Shranjeni izvozi:"
#: addons/web/static/src/xml/base.xml:0
msgid "Old Password:"
msgstr "Staro geslo:"
#: addons/web/static/src/xml/base.xml:0
msgid "New Password:"
msgstr "Novo geslo:"
#: addons/web/static/src/xml/base.xml:0
msgid "Confirm Password:"
msgstr "Potrditev gesla:"
#: addons/web/static/src/xml/base.xml:0
msgid "Import"
msgstr "Uvozi"
#: addons/web/static/src/xml/base.xml:0
msgid "1. Import a .CSV file"
msgstr "1. Uvozi .CSV datoteko"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"Select a .CSV file to import. If you need a sample of file to import,\n"
" you should use the export tool with the \"Import Compatible\" option."
msgstr ""
"Izberi datoteko .CSV za uvoz. Če potrebujete vzorec daoteke za uvoz,\n"
" uporabite orodje izvoza z možnostjo \"Uvozi kompatibilno\"."
#: addons/web/static/src/xml/base.xml:0
msgid "CSV File:"
msgstr "CSV datoteka:"
#: addons/web/static/src/xml/base.xml:0
msgid "2. Check your file format"
msgstr "2. Preveri format datoteke"
#: addons/web/static/src/xml/base.xml:0
msgid "Import Options"
msgstr "Možnosti uvoza"
#: addons/web/static/src/xml/base.xml:0
msgid "Does your file have titles?"
msgstr "Ali ima vaša datoteka naslove?"
#: addons/web/static/src/xml/base.xml:0
msgid "Separator:"
msgstr "Ločitelj:"
#: addons/web/static/src/xml/base.xml:0
msgid "Delimiter:"
msgstr "Razmejitelj:"
#: addons/web/static/src/xml/base.xml:0
msgid "Encoding:"
msgstr "Nabor znakov:"
#: addons/web/static/src/xml/base.xml:0
msgid "UTF-8"
msgstr "UTF-8"
#: addons/web/static/src/xml/base.xml:0
msgid "Latin 1"
msgstr "Latin 1"
#: addons/web/static/src/xml/base.xml:0
msgid "Lines to skip"
msgstr "Vrstice za preskočit"
#: addons/web/static/src/xml/base.xml:0
msgid "The import failed due to:"
msgstr "Uvoz ni uspel zaradi:"
#: addons/web/static/src/xml/base.xml:0
msgid "Here is a preview of the file we could not import:"
msgstr "Tukaj je predogled datoteke, ki je nismo mogli uvozit"
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP Web"
msgstr "OpenERP Web"
#: addons/web/static/src/xml/base.xml:0
msgid "Version"
msgstr "Različica"
#: addons/web/static/src/xml/base.xml:0
msgid "Copyright © 2011-TODAY OpenERP SA. All Rights Reserved."
msgstr "Copyright © 2011-DANES OpenERP SA. Vse pravice pridržane."
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP is a trademark of the"
msgstr "OpenERP je blagovna znamka"
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP SA Company"
msgstr "podjetja OpenERP SA"
#: addons/web/static/src/xml/base.xml:0
msgid "Licenced under the terms of"
msgstr "Licencirana pod pogoji"
#: addons/web/static/src/xml/base.xml:0
msgid "GNU Affero General Public License"
msgstr "GNU Affero General Public License"
#: addons/web/static/src/xml/base.xml:0
msgid "About OpenERP"
msgstr "O OpenERP"
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP"
msgstr "OpenERP"
#: addons/web/static/src/xml/base.xml:0
msgid ""
"is a free enterprise-scale software system that is designed to boost\n"
" productivity and profit through data integration. It connects, "
"improves and\n"
" manages business processes in areas such as sales, finance, "
"supply chain,\n"
" project management, production, services, CRM, etc..."
msgstr ""
"je brezplačna podjetniškega obsega sistemska programska oprema, ki je "
"namenjena za povečanje\n"
" produktivnosti in dobička skozi podatkovno integracijo. "
"Povezuje, izboljša in\n"
" upravlja poslovne procese v okoljih kot so prodaja, finance, "
"veriga dobavljanja,\n"
" upravljanje projektov, proizvodnje, storitev, CRM, itd..."
#: addons/web/static/src/xml/base.xml:0
msgid ""
"The system is platform-independent, and can be installed on Windows, Mac OS "
"X,\n"
" and various Linux and other Unix-based distributions. Its "
"architecture enables\n"
" new functionality to be rapidly created, modifications to be "
"made to a\n"
" production system and migration to a new version to be "
"straightforward."
msgstr ""
"Sistem je neodvisnen od platforme in ga je mogoče namestiti na Windows, Mac "
"OS X,\n"
" in na različne Linux in ostale Unix-bazirane distribucije. "
"Njegova arhitektura omogoča\n"
" nove funkcionalnosti, ki so lahko hitro ustvarjene, "
"modifikacija, ki se naredi v\n"
" produkcijskem sistemu in migracijo na novo verzijo, ki se "
"enostavno izvede."
#: addons/web/static/src/xml/base.xml:0
msgid ""
"Depending on your needs, OpenERP is available through a web or application "
"client."
msgstr ""
"Glede na vaše potrebe, je OpenERP na voljo prek spleta ali programskega "
"klienta."

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2011-09-06 12:02+0200\n"
"POT-Creation-Date: 2011-10-07 10:38+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -17,28 +17,40 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 0.9.6\n"
#: addons/web/static/src/js/form.js:1473
#: addons/web/static/src/js/view_form.js:355
msgid "Warning, the record has been modified, your changes will be discarded."
msgstr ""
#: addons/web/static/src/js/view_form.js:1659
msgid "<em>   Search More...</em>"
msgstr ""
#: addons/web/static/src/js/form.js:1486
#: addons/web/static/src/js/view_form.js:1672
#, python-format
msgid "<em>   Create \"<strong>%s</strong>\"</em>"
msgstr ""
#: addons/web/static/src/js/form.js:1492
#: addons/web/static/src/js/view_form.js:1678
msgid "<em>   Create and Edit...</em>"
msgstr ""
#: addons/web/static/src/js/views.js:484
#: addons/web/static/src/js/views.js:568
msgid "You must choose at least one record."
msgstr ""
#: addons/web/static/src/js/views.js:569
msgid "Warning"
msgstr ""
#: addons/web/static/src/js/views.js:609
msgid "Translations"
msgstr ""
#: addons/web/static/src/js/views.js:489 addons/web/static/src/xml/base.xml:0
#: addons/web/static/src/js/views.js:614 addons/web/static/src/xml/base.xml:0
msgid "Save"
msgstr ""
#: addons/web/static/src/js/views.js:490
#: addons/web/static/src/js/views.js:615
msgid "Close"
msgstr ""
@ -229,23 +241,31 @@ msgid "LOGOUT"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "h3"
msgid "&laquo;"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "<"
msgid "&raquo;"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid ">"
msgid "oe_secondary_menu_item"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "</"
msgid "oe_secondary_submenu_item"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "h4"
msgid "Hide this tip"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Disable all tips"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "View#"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
@ -284,6 +304,14 @@ msgstr ""
msgid "First"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "<"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid ">"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Last"
msgstr ""
@ -292,10 +320,6 @@ msgstr ""
msgid "♻"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "View#"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Save & Edit"
msgstr ""
@ -308,6 +332,14 @@ msgstr ""
msgid "New"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Duplicate"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Readonly/Editable"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "<<"
msgstr ""
@ -336,6 +368,14 @@ msgstr ""
msgid "?"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "#"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Done"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Open..."
msgstr ""
@ -508,6 +548,69 @@ msgstr ""
msgid "Confirm Password:"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Import"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "1. Import a .CSV file"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid ""
"Select a .CSV file to import. If you need a sample of file to import,\n"
" you should use the export tool with the \"Import Compatible\" "
"option."
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "CSV File:"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "2. Check your file format"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Import Options"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Does your file have titles?"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Separator:"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Delimiter:"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Encoding:"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "UTF-8"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Latin 1"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Lines to skip"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "The import failed due to:"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "Here is a preview of the file we could not import:"
msgstr ""
#: addons/web/static/src/xml/base.xml:0
msgid "OpenERP Web"
msgstr ""

View File

@ -0,0 +1,21 @@
Copyright 2011 Xavier Morel. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are
permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of
conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list
of conditions and the following disclaimer in the documentation and/or other materials
provided with the distribution.
THIS SOFTWARE IS PROVIDED BY XAVIER MOREL ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,59 @@
.. -*- restructuredtext -*-
In jQuery 1.5, jQuery has introduced a Deferred object in order to
better handle callbacks.
Along with Deferred, it introduced ``jQuery.when`` which allows, among
other things, for multiplexing deferreds (waiting on multiple
deferreds at the same time).
While this is very nice if all deferreds are available at the same
point, it doesn't really work if the resolution of a deferred can
generate more deferreds, or for collections of deferreds coming from
multiple sources (which may not be aware of one another).
Deferred.queue tries to be a solution to this. It is based on the
principle of FIFO multiple-producers multiple-consumers tasks queues,
such as Python's `queue.Queue`_. Any code with a reference to the
queue can add a promise to the queue, and the queue (which is a
promise itself) will only be resolved once all promises within are
resolved.
Quickstart
----------
Deferred.queue has a very simple life cycle: it is dormant when
created, it starts working as soon as promises get added to it (via
``.push``, or by providing them directly to its constructor), and as
soon as the last promise in the queue is resolved it resolves itself.
If any promise in the queue fails, the queue itself will be rejected
(without waiting for further promises).
Once a queue has been resolved or rejected, adding new promises to it
results in an error.
API
---
``jQuery.Deferred.queue([promises...])``
Creates a new deferred queue. Can be primed with a series of promise
objects.
``.push(promise...)``
Adds promises to the queue. Returns the queue itself (can be
chained).
If the queue has already been resolved or rejected, raises an error.
``.then([doneCallbacks][, failCallbacks])``
Promise/A ``then`` method.
``.done(doneCallbacks)``
jQuery ``done`` extension to promise objects
``.fail(failCallbacks)``
jQuery ``fail`` extension to promise objects
.. _queue.Queue:
http://docs.python.org/dev/library/queue.html

View File

@ -0,0 +1,34 @@
(function ($) {
"use strict";
$.extend($.Deferred, {
queue: function () {
var queueDeferred = $.Deferred();
var promises = 0;
function resolve() {
if (--promises > 0) {
return;
}
setTimeout($.proxy(queueDeferred, 'resolve'), 0);
}
var promise = $.extend(queueDeferred.promise(), {
push: function () {
if (this.isResolved() || this.isRejected()) {
throw new Error("Can not add promises to a resolved "
+ "or rejected promise queue");
}
promises += 1;
$.when.apply(null, arguments).then(
resolve, $.proxy(queueDeferred, 'reject'));
return this;
}
});
if (arguments.length) {
promise.push.apply(promise, arguments);
}
return promise;
}
});
})(jQuery)

View File

@ -0,0 +1,5 @@
repo: 076b192d0d8ab2b92d1dbcfa3da055382f30eaea
node: 87fb1b67d6a13f10a1a328104ee4d4b2c36801ec
branch: default
latesttag: 0.2
latesttagdistance: 1

View File

@ -0,0 +1 @@
Parser and evaluator of Python expressions

View File

@ -0,0 +1,14 @@
* Parser
since parsing expressions, try with a pratt parser
http://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/
http://effbot.org/zone/simple-top-down-parsing.htm
Evaluator
---------
* Stop busyworking trivial binary operator
* Make it *trivial* to build Python type-wrappers
* Implement Python's `data model
protocols<http://docs.python.org/reference/datamodel.html#basic-customization>`_
for *all* supported operations, optimizations can come later
* Automatically type-wrap everything (for now anyway)

View File

@ -0,0 +1,546 @@
var py = {};
(function (exports) {
var NUMBER = /^\d$/,
NAME_FIRST = /^[a-zA-Z_]$/,
NAME = /^[a-zA-Z0-9_]$/;
var create = function (o, props) {
function F() {}
F.prototype = o;
var inst = new F;
for(var name in props) {
if(!props.hasOwnProperty(name)) { continue; }
inst[name] = props[name];
}
return inst;
};
var symbols = {};
var comparators = {};
var Base = {
nud: function () { throw new Error(this.id + " undefined as prefix"); },
led: function (led) { throw new Error(this.id + " undefined as infix"); },
toString: function () {
if (this.id === '(constant)' || this.id === '(number)' || this.id === '(name)' || this.id === '(string)') {
return [this.id.slice(0, this.id.length-1), ' ', this.value, ')'].join('');
} else if (this.id === '(end)') {
return '(end)';
} else if (this.id === '(comparator)' ) {
var repr = ['(comparator', this.expressions[0]];
for (var i=0;i<this.operators.length; ++i) {
repr.push(this.operators[i], this.expressions[i+1]);
}
return repr.join(' ') + ')';
}
var out = [this.id, this.first, this.second, this.third]
.filter(function (r){return r}).join(' ');
return '(' + out + ')';
}
};
function symbol(id, bp) {
bp = bp || 0;
var s = symbols[id];
if (s) {
if (bp > s.lbp) {
s.lbp = bp;
}
return s;
}
return symbols[id] = create(Base, {
id: id,
lbp: bp
});
}
function constant(id) {
symbol(id).nud = function () {
this.id = "(constant)";
this.value = id;
return this;
};
}
function prefix(id, bp, nud) {
symbol(id).nud = nud || function () {
this.first = expression(bp);
return this
}
}
function infix(id, bp, led) {
symbol(id, bp).led = led || function (left) {
this.first = left;
this.second = expression(bp);
return this;
}
}
function infixr(id, bp) {
symbol(id, bp).led = function (left) {
this.first = left;
this.second = expression(bp - 1);
return this;
}
}
function comparator(id) {
comparators[id] = true;
var bp = 60;
infix(id, bp, function (left) {
this.id = '(comparator)';
this.operators = [id];
this.expressions = [left, expression(bp)];
while (token.id in comparators) {
this.operators.push(token.id);
advance();
this.expressions.push(
expression(bp));
}
return this;
});
}
constant('None'); constant('False'); constant('True');
symbol('(number)').nud = function () { return this; };
symbol('(name)').nud = function () { return this; };
symbol('(string)').nud = function () { return this; };
symbol('(end)');
symbol(':'); symbol(')'); symbol(']'); symbol('}'); symbol(',');
symbol('else');
symbol('lambda', 20).nud = function () {
this.first = [];
if (token.id !== ':') {
for(;;) {
if (token.id !== '(name)') {
throw new Error('Excepted an argument name');
}
this.first.push(token);
advance();
if (token.id !== ',') {
break;
}
advance(',');
}
}
advance(':');
this.second = expression();
return this;
};
infix('if', 20, function (left) {
this.first = left;
this.second = expression();
advance('else');
this.third = expression();
return this;
});
infixr('or', 30); infixr('and', 40); prefix('not', 50);
comparator('in'); comparator('not in');
comparator('is'); comparator('is not');
comparator('<'); comparator('<=');
comparator('>'); comparator('>=');
comparator('<>'); comparator('!='); comparator('==');
infix('|', 70); infix('^', 80), infix('&', 90);
infix('<<', 100); infix('>>', 100);
infix('+', 110); infix('-', 110);
infix('*', 120); infix('/', 120);
infix('//', 120), infix('%', 120);
prefix('-', 130); prefix('+', 130); prefix('~', 130);
infixr('**', 140);
infix('.', 150, function (left) {
if (token.id !== '(name)') {
throw new Error('Expected attribute name, got ', token.id);
}
this.first = left;
this.second = token;
advance();
return this;
});
symbol('(', 150).nud = function () {
this.first = [];
var comma = false;
if (token.id !== ')') {
while (true) {
if (token.id === ')') {
break;
}
this.first.push(expression());
if (token.id !== ',') {
break;
}
comma = true;
advance(',');
}
}
advance(')');
if (!this.first.length || comma) {
return this;
} else {
return this.first[0];
}
};
symbol('(').led = function (left) {
this.first = left;
this.second = [];
if (token.id !== ")") {
for(;;) {
this.second.push(expression());
if (token.id !== ',') {
break;
}
advance(',');
}
}
advance(")");
return this;
};
infix('[', 150, function (left) {
this.first = left;
this.second = expression();
advance("]");
return this;
});
symbol('[').nud = function () {
this.first = [];
if (token.id !== ']') {
for (;;) {
if (token.id === ']') {
break;
}
this.first.push(expression());
if (token.id !== ',') {
break;
}
advance(',');
}
}
advance(']');
return this;
};
symbol('{').nud = function () {
this.first = [];
if (token.id !== '}') {
for(;;) {
if (token.id === '}') {
break;
}
var key = expression();
advance(':');
var value = expression();
this.first.push([key, value]);
if (token.id !== ',') {
break;
}
advance(',');
}
}
advance('}');
return this;
};
var longops = {
'*': ['*'],
'<': ['<', '=', '>'],
'>': ['=', '>'],
'!': ['='],
'=': ['='],
'/': ['/']
};
function Tokenizer() {
this.states = ['initial'];
this.tokens = [];
}
Tokenizer.prototype = {
builder: function (empty) {
var key = this.states[0] + '_builder';
if (empty) {
var value = this[key];
delete this[key];
return value;
} else {
return this[key] = this[key] || [];
}
},
simple: function (type) {
this.tokens.push({type: type});
},
push: function (new_state) {
this.states.push(new_state);
},
pop: function () {
this.states.pop();
},
feed: function (str, index) {
var s = this.states;
return this[s[s.length - 1]](str, index);
},
initial: function (str, index) {
var character = str[index];
if (character in longops) {
var follow = longops[character];
for(var i=0, len=follow.length; i<len; ++i) {
if (str[index+1] === follow[i]) {
character += follow[i];
index++;
break;
}
}
}
if (character === ' ') {
return index+1;
} else if (character === '\0') {
this.tokens.push(symbols['(end)']);
return index + 1
} else if (character === '"' || character === "'") {
this.push('string');
return index + 1;
} else if (NUMBER.test(character)) {
this.push('number');
return index;
} else if (NAME_FIRST.test(character)) {
this.push('name');
return index;
} else if (character in symbols) {
this.tokens.push(create(symbols[character]));
return index + 1;
}
throw new Error("Tokenizing failure of <<" + str + ">> at index " + index
+ ", character [[" + character + "]]"
+ "; parsed so far: " + this.tokens);
},
string: function (str, index) {
var character = str[index];
if (character === '"' || character === "'") {
this.tokens.push(create(symbols['(string)'], {
value: this.builder(true).join('')
}));
this.pop();
return index + 1;
}
this.builder().push(character);
return index + 1;
},
number: function (str, index) {
var character = str[index];
if (!NUMBER.test(character)) {
this.tokens.push(create(symbols['(number)'], {
value: parseFloat(this.builder(true).join(''))
}));
this.pop();
return index;
}
this.builder().push(character);
return index + 1;
},
name: function (str, index) {
var character = str[index];
if (!NAME.test(character)) {
var name = this.builder(true).join('');
var symbol = symbols[name];
if (symbol) {
if (name === 'in' && this.tokens[this.tokens.length-1].id === 'not') {
symbol = symbols['not in'];
this.tokens.pop();
} else if (name === 'not' && this.tokens[this.tokens.length-1].id === 'is') {
symbol = symbols['is not'];
this.tokens.pop();
}
this.tokens.push(create(symbol));
} else {
this.tokens.push(create(symbols['(name)'], {
value: name
}));
}
this.pop();
return index;
}
this.builder().push(character);
return index + 1;
}
};
exports.tokenize = function tokenize(str) {
var index = 0,
tokenizer = new Tokenizer(str);
str += '\0';
do {
index = tokenizer.feed(str, index);
} while (index !== str.length);
return tokenizer.tokens;
};
var token, next;
function expression(rbp) {
rbp = rbp || 0;
var t = token;
token = next();
var left = t.nud();
while (rbp < token.lbp) {
t = token;
token = next();
left = t.led(left);
}
return left;
}
function advance(id) {
if (id && token.id !== id) {
throw new Error(
'Expected "' + id + '", got "' + token.id + '"');
}
token = next();
}
exports.object = create({}, {});
exports.bool = function (arg) { return !!arg; };
exports.tuple = create(exports.object, {
__contains__: function (value) {
for(var i=0, len=this.values.length; i<len; ++i) {
if (this.values[i] === value) {
return true;
}
}
return false;
},
toJSON: function () {
return this.values;
}
});
exports.list = exports.tuple;
exports.dict = create(exports.object, {
toJSON: function () {
return this.values;
}
});
exports.parse = function (toks) {
var index = 0;
token = toks[0];
next = function () { return toks[++index]; };
return expression();
};
var evaluate_operator = function (operator, a, b) {
switch (operator) {
case '==': case 'is': return a === b;
case '!=': case 'is not': return a !== b;
case '<': return a < b;
case '<=': return a <= b;
case '>': return a > b;
case '>=': return a >= b;
case 'in':
if (typeof b === 'string') {
return b.indexOf(a) !== -1;
}
return b.__contains__(a);
case 'not in':
if (typeof b === 'string') {
return b.indexOf(a) === -1;
}
return !b.__contains__(a);
}
throw new Error('SyntaxError: unknown comparator [[' + operator + ']]');
};
exports.evaluate = function (expr, context) {
switch (expr.id) {
case '(name)':
var val = context[expr.value];
if (val === undefined) {
throw new Error("NameError: name '" + expr.value + "' is not defined");
}
return val;
case '(string)':
case '(number)':
return expr.value;
case '(constant)':
if (expr.value === 'None')
return null;
else if (expr.value === 'False')
return false;
else if (expr.value === 'True')
return true;
throw new Error("SyntaxError: unknown constant '" + expr.value + "'");
case '(comparator)':
var result, left = exports.evaluate(expr.expressions[0], context);
for(var i=0; i<expr.operators.length; ++i) {
result = evaluate_operator(
expr.operators[i],
left,
left = exports.evaluate(expr.expressions[i+1], context));
if (!result) { return false; }
}
return true;
case '-':
if (expr.second) {
throw new Error('SyntaxError: binary [-] not implemented yet');
}
return -(exports.evaluate(expr.first, context));
case 'not':
return !(exports.evaluate(expr.first, context));
case 'and':
return (exports.evaluate(expr.first, context)
&& exports.evaluate(expr.second, context));
case 'or':
return (exports.evaluate(expr.first, context)
|| exports.evaluate(expr.second, context));
case '(':
if (expr.second) {
var fn = exports.evaluate(expr.first, context), args=[];
for (var jj=0; jj<expr.second.length; ++jj) {
args.push(exports.evaluate(
expr.second[jj], context));
}
return fn.apply(null, args);
}
var tuple_exprs = expr.first,
tuple_values = [];
for (var j=0, len=tuple_exprs.length; j<len; ++j) {
tuple_values.push(exports.evaluate(
tuple_exprs[j], context));
}
return create(exports.tuple, {values: tuple_values});
case '[':
if (expr.second) {
throw new Error('SyntaxError: indexing not implemented yet');
}
var list_exprs = expr.first, list_values = [];
for (var k=0; k<list_exprs.length; ++k) {
list_values.push(exports.evaluate(
list_exprs[k], context));
}
return create(exports.list, {values: list_values});
case '{':
var dict_exprs = expr.first, dict_values = {};
for(var l=0; l<dict_exprs.length; ++l) {
dict_values[exports.evaluate(dict_exprs[l][0], context)] =
exports.evaluate(dict_exprs[l][1], context);
}
return create(exports.dict, {values: dict_values});
case '.':
if (expr.second.id !== '(name)') {
throw new Error('SyntaxError: ' + expr);
}
return exports.evaluate(expr.first, context)[expr.second.value];
default:
throw new Error('SyntaxError: Unknown node [[' + expr.id + ']]');
}
};
exports.eval = function (str, context) {
return exports.evaluate(
exports.parse(
exports.tokenize(
str)),
context);
}
})(typeof exports === 'undefined' ? py : exports);

View File

@ -0,0 +1,90 @@
var py = require('../lib/py.js'),
assert = require('assert');
// Literals
assert.strictEqual(py.eval('1'), 1);
assert.strictEqual(py.eval('None'), null);
assert.strictEqual(py.eval('False'), false);
assert.strictEqual(py.eval('True'), true);
assert.strictEqual(py.eval('"somestring"'), 'somestring');
assert.strictEqual(py.eval("'somestring'"), 'somestring');
assert.deepEqual(py.eval("()").toJSON(), []);
assert.deepEqual(py.eval("[]").toJSON(), []);
assert.deepEqual(py.eval("{}").toJSON(), {});
assert.deepEqual(py.eval("(None, True, False, 0, 1, 'foo')").toJSON(),
[null, true, false, 0, 1, 'foo']);
assert.deepEqual(py.eval("[None, True, False, 0, 1, 'foo']").toJSON(),
[null, true, false, 0, 1, 'foo']);
assert.deepEqual(py.eval("{'foo': 1, foo: 2}", {foo: 'bar'}).toJSON(),
{foo: 1, bar: 2});
// Equality tests
assert.ok(py.eval(
"foo == 'foo'", {foo: 'foo'}));
// Inequality
assert.ok(py.eval(
"foo != bar", {foo: 'foo', bar: 'bar'}));
// Comparisons
assert.ok(py.eval('3 < 5'));
assert.ok(py.eval('5 >= 3'));
assert.ok(py.eval('3 >= 3'));
assert.ok(!py.eval('5 < 3'));
assert.ok(py.eval('1 < 3 < 5'));
assert.ok(py.eval('5 > 3 > 1'));
assert.ok(py.eval('1 < 3 > 2 == 2 > -2 not in (0, 1, 2)'));
// string rich comparisons
assert.ok(py.eval(
'date >= current', {date: '2010-06-08', current: '2010-06-05'}));
// Boolean operators
assert.ok(py.eval(
"foo == 'foo' or foo == 'bar'", {foo: 'bar'}));
assert.ok(py.eval(
"foo == 'foo' and bar == 'bar'", {foo: 'foo', bar: 'bar'}));
// - lazyness, second clauses NameError if not short-circuited
assert.ok(py.eval(
"foo == 'foo' or bar == 'bar'", {foo: 'foo'}));
assert.ok(!py.eval(
"foo == 'foo' and bar == 'bar'", {foo: 'bar'}));
// contains (in)
assert.ok(py.eval(
"foo in ('foo', 'bar')", {foo: 'bar'}));
assert.ok(py.eval('1 in (1, 2, 3, 4)'));
assert.ok(!py.eval('1 in (2, 3, 4)'));
assert.ok(py.eval('type in ("url",)', {type: 'url'}));
assert.ok(!py.eval('type in ("url",)', {type: 'ur'}));
assert.ok(py.eval('1 not in (2, 3, 4)'));
assert.ok(py.eval('type not in ("url",)', {type: 'ur'}));
assert.ok(py.eval(
"foo in ['foo', 'bar']", {foo: 'bar'}));
// string contains
assert.ok(py.eval('type in "view"', {type: 'view'}));
assert.ok(!py.eval('type in "view"', {type: 'bob'}));
assert.ok(py.eval('type in "url"', {type: 'ur'}));
// Literals
assert.strictEqual(py.eval('False'), false);
assert.strictEqual(py.eval('True'), true);
assert.strictEqual(py.eval('None'), null);
assert.ok(py.eval('foo == False', {foo: false}));
assert.ok(!py.eval('foo == False', {foo: true}));
// conversions
assert.strictEqual(
py.eval('bool(date_deadline)', {bool: py.bool, date_deadline: '2008'}),
true);
// getattr
assert.ok(py.eval('foo.bar', {foo: {bar: true}}));
assert.ok(!py.eval('foo.bar', {foo: {bar: false}}));
// complex expressions
assert.ok(py.eval(
"state=='pending' and not(date_deadline and (date_deadline < current_date))",
{state: 'pending', date_deadline: false}));
assert.ok(py.eval(
"state=='pending' and not(date_deadline and (date_deadline < current_date))",
{state: 'pending', date_deadline: '2010-05-08', current_date: '2010-05-08'}));;

View File

@ -207,6 +207,7 @@ QWeb2.Engine = (function() {
this.reserved_words = QWeb2.RESERVED_WORDS.slice(0);
this.actions_precedence = QWeb2.ACTIONS_PRECEDENCE.slice(0);
this.word_replacement = QWeb2.tools.extend({}, QWeb2.WORD_REPLACEMENT);
this.format_text_node = null;
for (var i = 0; i < arguments.length; i++) {
this.add_template(arguments[i]);
}
@ -317,12 +318,14 @@ QWeb2.Engine = (function() {
" dict = dict || {};\n" +
" dict['__template__'] = '" + template + "';\n" +
" var r = [];\n" +
" /* START TEMPLATE */ try {\n" +
" /* START TEMPLATE */" +
(this.debug ? "" : " try {\n") +
(e.compile()) + "\n" +
" /* END OF TEMPLATE */ } catch(error) {\n" +
" /* END OF TEMPLATE */" +
(this.debug ? "" : " } catch(error) {\n" +
" if (console && console.exception) console.exception(error);\n" +
" context.engine.tools.exception('Runtime Error: ' + error, context);\n" +
" }\n" +
" context.engine.tools.exception('Runtime Error: ' + error, context);\n") +
(this.debug ? "" : " }\n") +
" return r.join('');";
},
render : function(template, dict) {
@ -486,12 +489,16 @@ QWeb2.Element = (function() {
},
_compile : function() {
switch (this.node.nodeType) {
case 3:
case 4:
this.top_string(this.node.data);
case 3:
case 4:
var text = this.node.data;
if (this.engine.format_text_node) {
text = this.engine.format_text_node.call(this, text);
}
this.top_string(text);
break;
case 1:
this.compile_element();
case 1:
this.compile_element();
}
var r = this._top.join('');
if (this.process_children) {

View File

@ -4,301 +4,436 @@
// Documentation: https://github.com/edtsech/underscore.string
// Some code is borrowed from MooTools and Alexandru Marasteanu.
// Version 1.1.4
// Version 1.1.6
(function(){
// ------------------------- Baseline setup ---------------------------------
// Establish the root object, "window" in the browser, or "global" on the server.
var root = this;
(function(root){
'use strict';
var nativeTrim = String.prototype.trim;
if (typeof _ != 'undefined') {
var _reverse = _().reverse,
_include = _.include;
}
function str_repeat(i, m) {
for (var o = []; m > 0; o[--m] = i);
return o.join('');
// Defining helper functions.
var nativeTrim = String.prototype.trim;
var parseNumber = function(source) { return source * 1 || 0; };
var strRepeat = function(i, m) {
for (var o = []; m > 0; o[--m] = i);
return o.join('');
};
var slice = function(a){
return Array.prototype.slice.call(a);
};
var defaultToWhiteSpace = function(characters){
if (characters) {
return _s.escapeRegExp(characters);
}
return '\\s';
};
var sArgs = function(method){
return function(){
var args = slice(arguments);
for(var i=0; i<args.length; i++)
args[i] = args[i] == null ? '' : '' + args[i];
return method.apply(null, args);
};
};
// sprintf() for JavaScript 0.7-beta1
// http://www.diveintojavascript.com/projects/javascript-sprintf
//
// Copyright (c) Alexandru Marasteanu <alexaholic [at) gmail (dot] com>
// All rights reserved.
var sprintf = (function() {
function get_type(variable) {
return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase();
}
function defaultToWhiteSpace(characters){
if (characters) {
return _s.escapeRegExp(characters);
var str_repeat = strRepeat;
var str_format = function() {
if (!str_format.cache.hasOwnProperty(arguments[0])) {
str_format.cache[arguments[0]] = str_format.parse(arguments[0]);
}
return str_format.format.call(null, str_format.cache[arguments[0]], arguments);
};
str_format.format = function(parse_tree, argv) {
var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length;
for (i = 0; i < tree_length; i++) {
node_type = get_type(parse_tree[i]);
if (node_type === 'string') {
output.push(parse_tree[i]);
}
return '\\s';
}
var _s = {
isBlank: function(str){
return !!str.match(/^\s*$/);
},
capitalize : function(str) {
return str.charAt(0).toUpperCase() + str.substring(1).toLowerCase();
},
chop: function(str, step){
step = step || str.length;
var arr = [];
for (var i = 0; i < str.length;) {
arr.push(str.slice(i,i + step));
i = i + step;
else if (node_type === 'array') {
match = parse_tree[i]; // convenience purposes only
if (match[2]) { // keyword argument
arg = argv[cursor];
for (k = 0; k < match[2].length; k++) {
if (!arg.hasOwnProperty(match[2][k])) {
throw(sprintf('[_.sprintf] property "%s" does not exist', match[2][k]));
}
arg = arg[match[2][k]];
}
return arr;
},
} else if (match[1]) { // positional argument (explicit)
arg = argv[match[1]];
}
else { // positional argument (implicit)
arg = argv[cursor++];
}
clean: function(str){
return _s.strip(str.replace(/\s+/g, ' '));
},
if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) {
throw(sprintf('[_.sprintf] expecting number but found %s', get_type(arg)));
}
switch (match[8]) {
case 'b': arg = arg.toString(2); break;
case 'c': arg = String.fromCharCode(arg); break;
case 'd': arg = parseInt(arg, 10); break;
case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break;
case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break;
case 'o': arg = arg.toString(8); break;
case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break;
case 'u': arg = Math.abs(arg); break;
case 'x': arg = arg.toString(16); break;
case 'X': arg = arg.toString(16).toUpperCase(); break;
}
arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg);
pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' ';
pad_length = match[6] - String(arg).length;
pad = match[6] ? str_repeat(pad_character, pad_length) : '';
output.push(match[5] ? arg + pad : pad + arg);
}
}
return output.join('');
};
count: function(str, substr){
var count = 0, index;
for (var i=0; i < str.length;) {
index = str.indexOf(substr, i);
index >= 0 && count++;
i = i + (index >= 0 ? index : 0) + substr.length;
}
return count;
},
str_format.cache = {};
chars: function(str) {
return str.split('');
},
escapeHTML: function(str) {
return String(str||'').replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;')
.replace(/"/g, '&quot;').replace(/'/g, "&apos;");
},
unescapeHTML: function(str) {
return String(str||'').replace(/&amp;/g, '&').replace(/&lt;/g, '<').replace(/&gt;/g, '>')
.replace(/&quot;/g, '"').replace(/&apos;/g, "'");
},
escapeRegExp: function(str){
// From MooTools core 1.2.4
return String(str||'').replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1');
},
insert: function(str, i, substr){
var arr = str.split('');
arr.splice(i, 0, substr);
return arr.join('');
},
includes: function(str, needle){
return str.indexOf(needle) !== -1;
},
join: function(sep) {
// TODO: Could this be faster by converting
// arguments to Array and using array.join(sep)?
sep = String(sep);
var str = "";
for (var i=1; i < arguments.length; i += 1) {
str += String(arguments[i]);
if ( i !== arguments.length-1 ) {
str += sep;
str_format.parse = function(fmt) {
var _fmt = fmt, match = [], parse_tree = [], arg_names = 0;
while (_fmt) {
if ((match = /^[^\x25]+/.exec(_fmt)) !== null) {
parse_tree.push(match[0]);
}
else if ((match = /^\x25{2}/.exec(_fmt)) !== null) {
parse_tree.push('%');
}
else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) {
if (match[2]) {
arg_names |= 1;
var field_list = [], replacement_field = match[2], field_match = [];
if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
field_list.push(field_match[1]);
while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') {
if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
field_list.push(field_match[1]);
}
}
return str;
},
lines: function(str) {
return str.split("\n");
},
// reverse: function(str){
// return Array.prototype.reverse.apply(str.split('')).join('');
// },
splice: function(str, i, howmany, substr){
var arr = str.split('');
arr.splice(i, howmany, substr);
return arr.join('');
},
startsWith: function(str, starts){
return str.length >= starts.length && str.substring(0, starts.length) === starts;
},
endsWith: function(str, ends){
return str.length >= ends.length && str.substring(str.length - ends.length) === ends;
},
succ: function(str){
var arr = str.split('');
arr.splice(str.length-1, 1, String.fromCharCode(str.charCodeAt(str.length-1) + 1));
return arr.join('');
},
titleize: function(str){
var arr = str.split(' '),
word;
for (var i=0; i < arr.length; i++) {
word = arr[i].split('');
if(typeof word[0] !== 'undefined') word[0] = word[0].toUpperCase();
i+1 === arr.length ? arr[i] = word.join('') : arr[i] = word.join('') + ' ';
}
return arr.join('');
},
camelize: function(str){
return _s.trim(str).replace(/(\-|_|\s)+(.)?/g, function(match, separator, chr) {
return chr ? chr.toUpperCase() : '';
});
},
underscored: function(str){
return _s.trim(str).replace(/([a-z\d])([A-Z]+)/g, '$1_$2').replace(/\-|\s+/g, '_').toLowerCase();
},
dasherize: function(str){
return _s.trim(str).replace(/([a-z\d])([A-Z]+)/g, '$1-$2').replace(/^([A-Z]+)/, '-$1').replace(/\_|\s+/g, '-').toLowerCase();
},
trim: function(str, characters){
if (!characters && nativeTrim) {
return nativeTrim.call(str);
}
characters = defaultToWhiteSpace(characters);
return str.replace(new RegExp('\^[' + characters + ']+|[' + characters + ']+$', 'g'), '');
},
ltrim: function(str, characters){
characters = defaultToWhiteSpace(characters);
return str.replace(new RegExp('\^[' + characters + ']+', 'g'), '');
},
rtrim: function(str, characters){
characters = defaultToWhiteSpace(characters);
return str.replace(new RegExp('[' + characters + ']+$', 'g'), '');
},
truncate: function(str, length, truncateStr){
truncateStr = truncateStr || '...';
return str.slice(0,length) + truncateStr;
},
words: function(str, delimiter) {
delimiter = delimiter || " ";
return str.split(delimiter);
},
pad: function(str, length, padStr, type) {
var padding = '';
var padlen = 0;
if (!padStr) { padStr = ' '; }
else if (padStr.length > 1) { padStr = padStr[0]; }
switch(type) {
case "right":
padlen = (length - str.length);
padding = str_repeat(padStr, padlen);
str = str+padding;
break;
case "both":
padlen = (length - str.length);
padding = {
'left' : str_repeat(padStr, Math.ceil(padlen/2)),
'right': str_repeat(padStr, Math.floor(padlen/2))
};
str = padding.left+str+padding.right;
break;
default: // "left"
padlen = (length - str.length);
padding = str_repeat(padStr, padlen);;
str = padding+str;
}
return str;
},
lpad: function(str, length, padStr) {
return _s.pad(str, length, padStr);
},
rpad: function(str, length, padStr) {
return _s.pad(str, length, padStr, 'right');
},
lrpad: function(str, length, padStr) {
return _s.pad(str, length, padStr, 'both');
},
/**
* Credits for this function goes to
* http://www.diveintojavascript.com/projects/sprintf-for-javascript
*
* Copyright (c) Alexandru Marasteanu <alexaholic [at) gmail (dot] com>
* All rights reserved.
* */
sprintf: function(){
var i = 0, a, f = arguments[i++], o = [], m, p, c, x, s = '';
while (f) {
if (m = /^[^\x25]+/.exec(f)) {
o.push(m[0]);
}
else if (m = /^\x25{2}/.exec(f)) {
o.push('%');
}
else if (m = /^\x25(?:(\d+)\$)?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(f)) {
if (((a = arguments[m[1] || i++]) == null) || (a == undefined)) {
throw('Too few arguments.');
}
if (/[^s]/.test(m[7]) && (typeof(a) != 'number')) {
throw('Expecting number but found ' + typeof(a));
}
switch (m[7]) {
case 'b': a = a.toString(2); break;
case 'c': a = String.fromCharCode(a); break;
case 'd': a = parseInt(a); break;
case 'e': a = m[6] ? a.toExponential(m[6]) : a.toExponential(); break;
case 'f': a = m[6] ? parseFloat(a).toFixed(m[6]) : parseFloat(a); break;
case 'o': a = a.toString(8); break;
case 's': a = ((a = String(a)) && m[6] ? a.substring(0, m[6]) : a); break;
case 'u': a = Math.abs(a); break;
case 'x': a = a.toString(16); break;
case 'X': a = a.toString(16).toUpperCase(); break;
}
a = (/[def]/.test(m[7]) && m[2] && a >= 0 ? '+'+ a : a);
c = m[3] ? m[3] == '0' ? '0' : m[3].charAt(1) : ' ';
x = m[5] - String(a).length - s.length;
p = m[5] ? str_repeat(c, x) : '';
o.push(s + (m[4] ? a + p : p + a));
else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) {
field_list.push(field_match[1]);
}
else {
throw('Huh ?!');
throw('[_.sprintf] huh?');
}
f = f.substring(m[0].length);
}
}
return o.join('');
else {
throw('[_.sprintf] huh?');
}
match[2] = field_list;
}
else {
arg_names |= 2;
}
if (arg_names === 3) {
throw('[_.sprintf] mixing positional and named placeholders is not (yet) supported');
}
parse_tree.push(match);
}
}
else {
throw('[_.sprintf] huh?');
}
_fmt = _fmt.substring(match[0].length);
}
return parse_tree;
};
// Aliases
return str_format;
})();
_s.strip = _s.trim;
_s.lstrip = _s.ltrim;
_s.rstrip = _s.rtrim;
_s.center = _s.lrpad
_s.ljust = _s.lpad
_s.rjust = _s.rpad
// CommonJS module is defined
if (typeof window === 'undefined' && typeof module !== 'undefined') {
// Export module
module.exports = _s;
// Integrate with Underscore.js
} else if (typeof root._ !== 'undefined') {
root._.mixin(_s);
// Defining underscore.string
// Or define it
} else {
root._ = _s;
}
var _s = {
}());
isBlank: sArgs(function(str){
return (/^\s*$/).test(str);
}),
stripTags: sArgs(function(str){
return str.replace(/<\/?[^>]+>/ig, '');
}),
capitalize : sArgs(function(str) {
return str.charAt(0).toUpperCase() + str.substring(1).toLowerCase();
}),
chop: sArgs(function(str, step){
step = parseNumber(step) || str.length;
var arr = [];
for (var i = 0; i < str.length;) {
arr.push(str.slice(i,i + step));
i = i + step;
}
return arr;
}),
clean: sArgs(function(str){
return _s.strip(str.replace(/\s+/g, ' '));
}),
count: sArgs(function(str, substr){
var count = 0, index;
for (var i=0; i < str.length;) {
index = str.indexOf(substr, i);
index >= 0 && count++;
i = i + (index >= 0 ? index : 0) + substr.length;
}
return count;
}),
chars: sArgs(function(str) {
return str.split('');
}),
escapeHTML: sArgs(function(str) {
return str.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;')
.replace(/"/g, '&quot;').replace(/'/g, "&apos;");
}),
unescapeHTML: sArgs(function(str) {
return str.replace(/&lt;/g, '<').replace(/&gt;/g, '>')
.replace(/&quot;/g, '"').replace(/&apos;/g, "'").replace(/&amp;/g, '&');
}),
escapeRegExp: sArgs(function(str){
// From MooTools core 1.2.4
return str.replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1');
}),
insert: sArgs(function(str, i, substr){
var arr = str.split('');
arr.splice(parseNumber(i), 0, substr);
return arr.join('');
}),
includes: sArgs(function(str, needle){
return str.indexOf(needle) !== -1;
}),
include: function(obj, needle) {
if (!_include || (/string|number/).test(typeof obj)) {
return this.includes(obj, needle);
} else {
return _include(obj, needle);
}
},
join: sArgs(function(sep) {
var args = slice(arguments);
return args.join(args.shift());
}),
lines: sArgs(function(str) {
return str.split("\n");
}),
reverse: function(obj){
if (!_reverse || (/string|number/).test(typeof obj)) {
return Array.prototype.reverse.apply(String(obj).split('')).join('');
} else {
return _reverse.call(_(obj));
}
},
splice: sArgs(function(str, i, howmany, substr){
var arr = str.split('');
arr.splice(parseNumber(i), parseNumber(howmany), substr);
return arr.join('');
}),
startsWith: sArgs(function(str, starts){
return str.length >= starts.length && str.substring(0, starts.length) === starts;
}),
endsWith: sArgs(function(str, ends){
return str.length >= ends.length && str.substring(str.length - ends.length) === ends;
}),
succ: sArgs(function(str){
var arr = str.split('');
arr.splice(str.length-1, 1, String.fromCharCode(str.charCodeAt(str.length-1) + 1));
return arr.join('');
}),
titleize: sArgs(function(str){
var arr = str.split(' '),
word;
for (var i=0; i < arr.length; i++) {
word = arr[i].split('');
if(typeof word[0] !== 'undefined') word[0] = word[0].toUpperCase();
i+1 === arr.length ? arr[i] = word.join('') : arr[i] = word.join('') + ' ';
}
return arr.join('');
}),
camelize: sArgs(function(str){
return _s.trim(str).replace(/(\-|_|\s)+(.)?/g, function(match, separator, chr) {
return chr ? chr.toUpperCase() : '';
});
}),
underscored: function(str){
return _s.trim(str).replace(/([a-z\d])([A-Z]+)/g, '$1_$2').replace(/\-|\s+/g, '_').toLowerCase();
},
dasherize: function(str){
return _s.trim(str).replace(/([a-z\d])([A-Z]+)/g, '$1-$2').replace(/^([A-Z]+)/, '-$1').replace(/\_|\s+/g, '-').toLowerCase();
},
trim: sArgs(function(str, characters){
if (!characters && nativeTrim) {
return nativeTrim.call(str);
}
characters = defaultToWhiteSpace(characters);
return str.replace(new RegExp('\^[' + characters + ']+|[' + characters + ']+$', 'g'), '');
}),
ltrim: sArgs(function(str, characters){
characters = defaultToWhiteSpace(characters);
return str.replace(new RegExp('\^[' + characters + ']+', 'g'), '');
}),
rtrim: sArgs(function(str, characters){
characters = defaultToWhiteSpace(characters);
return str.replace(new RegExp('[' + characters + ']+$', 'g'), '');
}),
truncate: sArgs(function(str, length, truncateStr){
truncateStr = truncateStr || '...';
length = parseNumber(length);
return str.length > length ? str.slice(0,length) + truncateStr : str;
}),
words: function(str, delimiter) {
return String(str).split(delimiter || " ");
},
pad: sArgs(function(str, length, padStr, type) {
var padding = '',
padlen = 0;
length = parseNumber(length);
if (!padStr) { padStr = ' '; }
else if (padStr.length > 1) { padStr = padStr.charAt(0); }
switch(type) {
case 'right':
padlen = (length - str.length);
padding = strRepeat(padStr, padlen);
str = str+padding;
break;
case 'both':
padlen = (length - str.length);
padding = {
'left' : strRepeat(padStr, Math.ceil(padlen/2)),
'right': strRepeat(padStr, Math.floor(padlen/2))
};
str = padding.left+str+padding.right;
break;
default: // 'left'
padlen = (length - str.length);
padding = strRepeat(padStr, padlen);;
str = padding+str;
}
return str;
}),
lpad: function(str, length, padStr) {
return _s.pad(str, length, padStr);
},
rpad: function(str, length, padStr) {
return _s.pad(str, length, padStr, 'right');
},
lrpad: function(str, length, padStr) {
return _s.pad(str, length, padStr, 'both');
},
sprintf: sprintf,
vsprintf: function(fmt, argv){
argv.unshift(fmt);
return sprintf.apply(null, argv);
},
toNumber: function(str, decimals) {
var num = parseNumber(parseNumber(str).toFixed(parseNumber(decimals)));
return (!(num === 0 && (str !== "0" && str !== 0))) ? num : Number.NaN;
},
strRight: sArgs(function(sourceStr, sep){
var pos = (!sep) ? -1 : sourceStr.indexOf(sep);
return (pos != -1) ? sourceStr.slice(pos+sep.length, sourceStr.length) : sourceStr;
}),
strRightBack: sArgs(function(sourceStr, sep){
var pos = (!sep) ? -1 : sourceStr.lastIndexOf(sep);
return (pos != -1) ? sourceStr.slice(pos+sep.length, sourceStr.length) : sourceStr;
}),
strLeft: sArgs(function(sourceStr, sep){
var pos = (!sep) ? -1 : sourceStr.indexOf(sep);
return (pos != -1) ? sourceStr.slice(0, pos) : sourceStr;
}),
strLeftBack: sArgs(function(sourceStr, sep){
var pos = sourceStr.lastIndexOf(sep);
return (pos != -1) ? sourceStr.slice(0, pos) : sourceStr;
})
};
// Aliases
_s.strip = _s.trim;
_s.lstrip = _s.ltrim;
_s.rstrip = _s.rtrim;
_s.center = _s.lrpad;
_s.ljust = _s.lpad;
_s.rjust = _s.rpad;
// CommonJS module is defined
if (typeof module !== 'undefined' && module.exports) {
// Export module
module.exports = _s;
// Integrate with Underscore.js
} else if (typeof root._ !== 'undefined') {
root._.mixin(_s);
// Or define it
} else {
root._ = _s;
}
}(this || window));

View File

@ -40,6 +40,9 @@ body.openerp, .openerp textarea, .openerp input, .openerp select, .openerp optio
}
/* Loading */
.loading {
cursor: wait;
}
.openerp .loading {
display: none;
z-index: 100;
@ -125,7 +128,7 @@ body.openerp, .openerp textarea, .openerp input, .openerp select, .openerp optio
margin-top: 5px;
text-align: center;
}
.openerp .login.login_invalid .login_error_message {
.openerp .login .login_invalid .login_error_message {
display: block;
}
@ -156,7 +159,7 @@ body.openerp, .openerp textarea, .openerp input, .openerp select, .openerp optio
}
.db_container {
width: 15%;
width: 196px;
background: #666666;
}
@ -222,6 +225,7 @@ label.error {
background: #f0eeee;
}
.openerp .oe-application-container {
width: 100%;
height: 100%;
}
@ -300,7 +304,7 @@ label.error {
text-shadow: 0 1px 0 #333;
text-align: center;
font-size: 18px;
line-height: 14px;
line-height: 18px;
right: 0;
}
.openerp .secondary_menu.oe_folded .oe_toggle_secondary_menu {
@ -325,6 +329,7 @@ label.error {
background: #5A5858;
vertical-align: top;
height: 100%;
display: block;
position: relative;
}
.openerp .secondary_menu.oe_folded {
@ -721,11 +726,15 @@ label.error {
.openerp .oe-listview .oe-field-cell {
cursor: pointer;
}
.openerp .oe-listview .oe-field-cell progress {
width: 100%;
}
.openerp .oe-listview .oe-field-cell button {
margin: 0;
padding: 0;
border: none;
background: none;
width: 100%;
width: 16px;
}
.openerp .oe-listview .oe-field-cell button:active {
opacity: 0.5;
@ -767,6 +776,10 @@ label.error {
.openerp .oe-listview .oe-list-footer span {
margin: 0 1em;
}
.openerp .oe-listview .oe-list-footer progress {
vertical-align:-10% !important;
width: 100%;
}
/** list rounded corners
@ -788,13 +801,15 @@ label.error {
-moz-border-radius-topright: 7px;
border-top-right-radius: 7px;
}
.openerp .oe-listview table.oe-listview-content tfoot td:first-child,
.openerp .oe-listview table.oe-listview-content tfoot tr:last-child th:first-child,
.openerp .oe-listview table.oe-listview-content tfoot tr:last-child td:first-child,
.openerp .oe-listview table.oe-listview-content tbody:last-child tr:last-child th:first-child {
-webkit-border-bottom-left-radius: 7px;
-moz-border-radius-bottomleft: 7px;
border-bottom-left-radius: 7px;
}
.openerp .oe-listview table.oe-listview-content tfoot td:last-child,
.openerp .oe-listview table.oe-listview-content tfoot tr:last-child th:last-child,
.openerp .oe-listview table.oe-listview-content tfoot tr:last-child td:last-child,
.openerp .oe-listview table.oe-listview-content tbody:last-child tr:last-child td:last-child {
-webkit-border-bottom-right-radius: 7px;
-moz-border-radius-bottomright: 7px;
@ -828,6 +843,9 @@ label.error {
}
/* Form */
.openerp .oe_frame.oe_forms {
clear: both;
}
.openerp table.oe_frame td {
color: #4c4c4c;
}
@ -855,7 +873,7 @@ label.error {
cursor: help;
}
.openerp .oe_form_field label.oe_label, .openerp .oe_form_field label.oe_label_help {
.openerp .oe_forms label.oe_label, .openerp .oe_forms label.oe_label_help {
text-align: right;
margin: 3px 0 0 10px;
}
@ -943,7 +961,7 @@ label.error {
position: relative;
}
.openerp input.oe-binary-file {
z-index: 2;
z-index: 0;
line-height: 0;
font-size: 50px;
position: absolute;
@ -1357,19 +1375,20 @@ label.error {
}
ul.oe-arrow-list {
padding-left: 0.5em;
padding-left: 1.1em;
margin: 0;
white-space: nowrap;
}
ul.oe-arrow-list li {
display: inline-block;
margin-left: -0.5em;
margin-left: -1em;
}
ul.oe-arrow-list li span {
vertical-align: top;
display: inline-block;
border-width:1em;
border-style:solid;
border-color: white;
border-color: #DEDEDE;
line-height:0em;
}
ul.oe-arrow-list .oe-arrow-list-before {
@ -1378,16 +1397,16 @@ ul.oe-arrow-list .oe-arrow-list-before {
}
ul.oe-arrow-list .oe-arrow-list-after {
border-color: rgba(0,0,0,0);
border-left-color: white;
border-left-color: #DEDEDE;
border-right-width:0;
}
ul.oe-arrow-list li.oe-arrow-list-selected span {
border-color: #CFCCCC;
border-color: #B5B9FF;
}
ul.oe-arrow-list li.oe-arrow-list-selected .oe-arrow-list-before {
border-left-color: rgba(0,0,0,0);
}
ul.oe-arrow-list li.oe-arrow-list-selected .oe-arrow-list-after {
border-color: rgba(0,0,0,0);
border-left-color: #CFCCCC;
border-left-color: #B5B9FF;
}

View File

@ -0,0 +1,30 @@
.openerp .oe_import_grid {
border: none;
border-collapse: collapse;
}
.openerp .oe_import_grid-header .oe_import_grid-cell {
background: url(../img/gradientlinebg.gif) repeat-x #CCCCCC;
border-bottom: 1px solid #E3E3E3;
font-weight: bold;
text-align: left;
}
.openerp .oe_import_grid-row .oe_import_grid-cell {
border-bottom: 1px solid #E3E3E3;
}
.openerp .separator.horizontal {
font-weight: bold;
border-bottom-width: 1px;
margin: 6px 4px 6px 1px;
height: 20px;
}
.openerp .duplicate_fld{
background-color:#FF6666;
}
.openerp .select_fld{
background: none repeat scroll 0 0 white;
}
.openerp .ui-autocomplete {
max-height: 300px;
overflow-y: auto;
padding-right: 20px;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 B

View File

@ -19,9 +19,9 @@
/**
* OpenERP instance constructor
*
* @param {Boolean} skip_init if true, skips the built-in initialization
* @param {Array} modules list of modules to initialize
*/
init: function(skip_init) {
init: function(modules) {
var new_instance = {
// links to the global openerp
_openerp: openerp,
@ -35,8 +35,9 @@
web_mobile: {}
};
openerp.sessions[new_instance._session_id] = new_instance;
if (!skip_init){
openerp.web(new_instance);
modules = modules || ["web"];
for(var i=0; i < modules.length; i++) {
openerp[modules[i]](new_instance);
}
return new_instance;
}
@ -58,7 +59,7 @@ openerp.web = function(instance) {
openerp.web.formats(instance);
openerp.web.chrome(instance);
openerp.web.data(instance);
var files = ["views","search","list","form","list_editable","web_mobile","view_tree","data_export"];
var files = ["views","search","list","form","list_editable","web_mobile","view_tree","data_export","data_import"];
for(var i=0; i<files.length; i++) {
if(openerp.web[files[i]]) {
openerp.web[files[i]](instance);

View File

@ -1,20 +1,20 @@
/*---------------------------------------------------------
* OpenERP Web chrome
*---------------------------------------------------------*/
openerp.web.chrome = function(openerp) {
var QWeb = openerp.web.qweb;
openerp.web.Notification = openerp.web.Widget.extend(/** @lends openerp.web.Notification# */{
/**
* @constructs openerp.web.Notification
* @extends openerp.web.Widget
*
* @param parent
* @param element_id
*/
init: function(parent, element_id) {
this._super(parent, element_id);
template: 'Notification',
identifier_prefix: 'notification-',
init: function() {
this._super.apply(this, arguments);
openerp.notification = this;
},
start: function() {
this._super.apply(this, arguments);
this.$element.notify({
speed: 500,
expires: 1500
@ -29,9 +29,12 @@ openerp.web.Notification = openerp.web.Widget.extend(/** @lends openerp.web.Not
warn: function(title, text) {
this.$element.notify('create', 'oe_notification_alert', {
title: title,
text: text
text: text,
}, {
expires: false,
});
}
},
});
openerp.web.Dialog = openerp.web.OldWidget.extend(/** @lends openerp.web.Dialog# */{
@ -129,24 +132,15 @@ openerp.web.Dialog = openerp.web.OldWidget.extend(/** @lends openerp.web.Dialog#
// Destroy widget
this.close();
this.$dialog.dialog('destroy');
this._super();
}
});
openerp.web.CrashManager = openerp.web.Dialog.extend(/** @lends openerp.web.CrashManager# */{
identifier_prefix: 'dialog_crash',
/**
* @constructs opener.web.CrashManager
* @extends openerp.web.Dialog
*
* @param parent
*/
openerp.web.CrashManager = openerp.web.SessionAware.extend({
init: function(parent) {
this._super(parent);
this._super((parent || {}).session);
this.session.on_rpc_error.add(this.on_rpc_error);
},
on_button_Ok: function() {
this.close();
},
on_rpc_error: function(error) {
this.error = error;
if (error.data.fault_code) {
@ -157,20 +151,36 @@ openerp.web.CrashManager = openerp.web.Dialog.extend(/** @lends openerp.web.Cras
}
}
if (error.code === 200 && error.type) {
this.dialog_title = "OpenERP " + _.capitalize(error.type);
this.template = 'DialogWarning';
this.open({
width: 'auto',
height: 'auto'
});
this.on_managed_error(error);
} else {
this.dialog_title = "OpenERP Error";
this.template = 'DialogTraceback';
this.open({
width: 'auto',
height: 'auto'
});
this.on_traceback(error);
}
},
on_managed_error: function(error) {
$('<div>' + QWeb.render('DialogWarning', {error: error}) + '</div>').dialog({
title: "OpenERP " + _.capitalize(error.type),
buttons: {
Ok: function() {
$(this).dialog("close");
}
}
});
},
on_traceback: function(error) {
var dialog = new openerp.web.Dialog(this, {
title: "OpenERP " + _.capitalize(error.type),
autoOpen: true,
width: '90%',
height: '90%',
min_width: '800px',
min_height: '600px',
buttons: {
Ok: function() {
$(this).dialog("close");
}
}
}).start();
dialog.$element.html(QWeb.render('DialogTraceback', {error: error}));
}
});
@ -194,8 +204,10 @@ openerp.web.Loading = openerp.web.Widget.extend(/** @lends openerp.web.Loading#
//this.$element.html(QWeb.render("Loading", {}));
this.$element.html("Loading ("+this.count+")");
this.$element.show();
this.widget_parent.$element.addClass('loading');
} else {
this.$element.fadeOut();
this.widget_parent.$element.removeClass('loading');
}
}
});
@ -218,9 +230,8 @@ openerp.web.Database = openerp.web.Widget.extend(/** @lends openerp.web.Database
this.$element.closest(".openerp")
.removeClass("login-mode")
.addClass("database_block");
var self = this;
var fetch_db = this.rpc("/web/database/get_list", {}, function(result) {
self.db_list = result.db_list;
});
@ -232,7 +243,7 @@ openerp.web.Database = openerp.web.Widget.extend(/** @lends openerp.web.Database
self.lang_list = result.lang_list;
});
$.when(fetch_db, fetch_langs).then(function () {self.do_create();});
this.$element.find('#db-create').click(this.do_create);
this.$element.find('#db-drop').click(this.do_drop);
this.$element.find('#db-backup').click(this.do_backup);
@ -254,7 +265,7 @@ openerp.web.Database = openerp.web.Widget.extend(/** @lends openerp.web.Database
.removeClass("database_block")
.end()
.empty();
this._super();
},
/**
* Converts a .serializeArray() result into a dict. Does not bother folding
@ -300,9 +311,9 @@ openerp.web.Database = openerp.web.Widget.extend(/** @lends openerp.web.Database
var admin = result[1][0];
setTimeout(function () {
self.stop();
self.widget_parent.do_login(
info.db, admin.login, admin.password);
self.stop();
$.unblockUI();
});
});
@ -370,7 +381,7 @@ openerp.web.Database = openerp.web.Widget.extend(/** @lends openerp.web.Database
}
$db_list.find(':selected').remove();
self.db_list.splice(_.indexOf(self.db_list, db, true), 1);
self.notification.notify("Dropping database", "The database '" + db + "' has been dropped");
self.do_notify("Dropping database", "The database '" + db + "' has been dropped");
});
}
});
@ -399,7 +410,7 @@ openerp.web.Database = openerp.web.Widget.extend(/** @lends openerp.web.Database
do_restore: function() {
var self = this;
self.$option_id.html(QWeb.render("RestoreDB", self));
self.$option_id.find("form[name=restore_db_form]").validate({
submitHandler: function (form) {
$.blockUI({message:'<img src="/web/static/src/img/throbber2.gif">'});
@ -455,7 +466,7 @@ openerp.web.Database = openerp.web.Widget.extend(/** @lends openerp.web.Database
self.display_error(result);
return;
}
self.notification.notify("Changed Password", "Password has been changed successfully");
self.do_notify("Changed Password", "Password has been changed successfully");
});
}
});
@ -463,41 +474,43 @@ openerp.web.Database = openerp.web.Widget.extend(/** @lends openerp.web.Database
});
openerp.web.Login = openerp.web.Widget.extend(/** @lends openerp.web.Login# */{
remember_creditentials: true,
remember_credentials: true,
template: "Login",
identifier_prefix: 'oe-app-login-',
/**
* @constructs openerp.web.Login
* @extends openerp.web.Widget
*
*
* @param parent
* @param element_id
*/
init: function(parent, element_id) {
this._super(parent, element_id);
init: function(parent) {
this._super(parent);
this.has_local_storage = typeof(localStorage) != 'undefined';
this.selected_db = null;
this.selected_login = null;
if (this.has_local_storage && this.remember_creditentials) {
if (this.has_local_storage && this.remember_credentials) {
this.selected_db = localStorage.getItem('last_db_login_success');
this.selected_login = localStorage.getItem('last_login_login_success');
if (jQuery.deparam(jQuery.param.querystring()).debug != undefined) {
this.selected_password = localStorage.getItem('last_password_login_success');
}
}
var qs = jQuery.deparam(jQuery.param.querystring());
if (qs.db) {
this.selected_db = qs.db;
}
if (qs.login) {
this.selected_login = qs.login;
}
},
start: function() {
var self = this;
this.rpc("/web/database/get_list", {}, function(result) {
self.db_list = result.db_list;
self.display();
}, function() {
self.display();
});
},
display: function() {
var self = this;
this.$element.html(QWeb.render("Login", this));
this.database = new openerp.web.Database(
this, "oe_database", "oe_db_options");
@ -506,6 +519,17 @@ openerp.web.Login = openerp.web.Widget.extend(/** @lends openerp.web.Login# */{
});
this.$element.find("form").submit(this.on_submit);
this.rpc("/web/database/get_list", {}, function(result) {
var tpl = openerp.web.qweb.render('Login_dblist', {db_list: result.db_list, selected_db: self.selected_db});
self.$element.find("input[name=db]").replaceWith(tpl)
},
function(error, event) {
if (error.data.fault_code === 'AccessDenied') {
event.preventDefault();
}
});
},
on_login_invalid: function() {
this.$element.closest(".openerp").addClass("login-mode");
@ -534,7 +558,7 @@ openerp.web.Login = openerp.web.Widget.extend(/** @lends openerp.web.Login# */{
this.session.session_login(db, login, password, function() {
if(self.session.session_is_valid()) {
if (self.has_local_storage) {
if(self.remember_creditentials) {
if(self.remember_credentials) {
localStorage.setItem('last_db_login_success', db);
localStorage.setItem('last_login_login_success', login);
if (jQuery.deparam(jQuery.param.querystring()).debug != undefined) {
@ -574,7 +598,7 @@ openerp.web.Header = openerp.web.Widget.extend(/** @lends openerp.web.Header# *
/**
* @constructs openerp.web.Header
* @extends openerp.web.Widget
*
*
* @param parent
*/
init: function(parent) {
@ -665,7 +689,7 @@ openerp.web.Header = openerp.web.Widget.extend(/** @lends openerp.web.Header# *
});
});
},
on_action: function(action) {
},
on_preferences: function(){
@ -713,7 +737,7 @@ openerp.web.Header = openerp.web.Widget.extend(/** @lends openerp.web.Header# *
action_manager.appendTo(this.dialog);
action_manager.render(this.dialog);
},
change_password :function() {
var self = this;
this.dialog = new openerp.web.Dialog(this,{
@ -758,7 +782,7 @@ openerp.web.Menu = openerp.web.Widget.extend(/** @lends openerp.web.Menu# */{
/**
* @constructs openerp.web.Menu
* @extends openerp.web.Widget
*
*
* @param parent
* @param element_id
* @param secondary_menu_id
@ -776,9 +800,8 @@ openerp.web.Menu = openerp.web.Widget.extend(/** @lends openerp.web.Menu# */{
},
start: function() {
this.$secondary_menu.addClass(this.folded ? 'oe_folded' : 'oe_unfolded');
this.reload();
},
reload: function() {
do_reload: function() {
this.rpc("/web/menu/load", {}, this.on_loaded);
},
on_loaded: function(data) {
@ -820,7 +843,9 @@ openerp.web.Menu = openerp.web.Widget.extend(/** @lends openerp.web.Menu# */{
this.session.active_id = id;
this.rpc('/web/menu/action', {'menu_id': id}, this.on_menu_action_loaded);
}
ev.stopPropagation();
if (ev) {
ev.stopPropagation();
}
return false;
},
do_menu_click: function($clicked_menu, manual) {
@ -863,6 +888,7 @@ openerp.web.Menu = openerp.web.Widget.extend(/** @lends openerp.web.Menu# */{
$sub_menu.hide();
return true;
}
return manual;
} else {
return true;
}
@ -910,7 +936,7 @@ openerp.web.WebClient = openerp.web.Widget.extend(/** @lends openerp.web.WebClie
/**
* @constructs openerp.web.WebClient
* @extends openerp.web.Widget
*
*
* @param element_id
*/
init: function(element_id) {
@ -924,16 +950,13 @@ openerp.web.WebClient = openerp.web.Widget.extend(/** @lends openerp.web.WebClie
}
this.$element.html(QWeb.render("Interface", params));
this.notification = new openerp.web.Notification();
this.session = new openerp.web.Session();
this.loading = new openerp.web.Loading(this,"oe_loading");
this.crashmanager = new openerp.web.CrashManager(this);
this.crashmanager.start();
// Do you autorize this ? will be replaced by notify() in controller
openerp.web.Widget.prototype.notification = new openerp.web.Notification(this, "oe_notification");
this.header = new openerp.web.Header(this);
this.login = new openerp.web.Login(this, "oe_login");
this.login = new openerp.web.Login(this);
this.header.on_logout.add(this.login.on_logout);
this.header.on_action.add(this.on_menu_action);
@ -951,12 +974,27 @@ openerp.web.WebClient = openerp.web.Widget.extend(/** @lends openerp.web.WebClie
},
start: function() {
this._super.apply(this, arguments);
this.notification.prependTo(this.$element);
this.header.appendTo($("#oe_header"));
this.session.start();
this.login.start();
this.login.appendTo($('#oe_login'));
this.menu.start();
},
do_reload: function() {
this.session.session_restore();
this.menu.do_reload();
},
do_notify: function() {
var n = this.notification;
n.notify.apply(n, arguments);
},
do_warn: function() {
var n = this.notification;
n.warn.apply(n, arguments);
},
on_logged: function() {
this.menu.do_reload();
if(this.action_manager)
this.action_manager.stop();
this.action_manager = new openerp.web.ActionManager(this);
@ -1000,7 +1038,7 @@ openerp.web.WebClient = openerp.web.Widget.extend(/** @lends openerp.web.WebClie
self.execute_home_action(home_action[0], ds);
})
},
default_home: function () {
default_home: function () {
},
/**
* Bundles the execution of the home action
@ -1025,7 +1063,6 @@ openerp.web.WebClient = openerp.web.Widget.extend(/** @lends openerp.web.WebClie
},
do_url_set_hash: function(url) {
if(!this.url_external_hashchange) {
console.log("url set #hash to",url);
this.url_internal_hashchange = true;
jQuery.bbq.pushState(url);
}
@ -1033,10 +1070,8 @@ openerp.web.WebClient = openerp.web.Widget.extend(/** @lends openerp.web.WebClie
on_url_hashchange: function() {
if(this.url_internal_hashchange) {
this.url_internal_hashchange = false;
console.log("url jump to FLAG OFF");
} else {
var url = jQuery.deparam.fragment();
console.log("url jump to",url);
this.url_external_hashchange = true;
this.action_manager.on_url_hashchange(url);
this.url_external_hashchange = false;
@ -1046,7 +1081,8 @@ openerp.web.WebClient = openerp.web.Widget.extend(/** @lends openerp.web.WebClie
this.action_manager.do_action(action);
},
do_about: function() {
}
},
});
};

View File

@ -10,8 +10,6 @@ if (!console.debug) {
}
openerp.web.core = function(openerp) {
openerp.web.qweb = new QWeb2.Engine();
openerp.web.qweb.debug = (window.location.search.indexOf('?debug') !== -1);
/**
* John Resig Class with factory improvement
*/
@ -287,14 +285,12 @@ openerp.web.Registry = openerp.web.Class.extend( /** @lends openerp.web.Registry
*/
get_any: function (keys) {
for (var i=0; i<keys.length; ++i) {
try {
return this.get_object(keys[i]);
} catch (e) {
if (e instanceof openerp.web.KeyNotFound) {
continue;
}
throw e;
var key = keys[i];
if (key === undefined || !(key in this.map)) {
continue;
}
return this.get_object(key);
}
throw new openerp.web.KeyNotFound(keys.join(','));
},
@ -365,6 +361,9 @@ openerp.web.Session = openerp.web.CallbackEnabled.extend( /** @lends openerp.web
this.context = {};
this.shortcuts = [];
this.active_id = null;
// TODO: session should have an optional name indicating that they'll
// be saved to (and revived from) cookies
this.name = 'session';
},
start: function() {
this.session_restore();
@ -386,6 +385,8 @@ openerp.web.Session = openerp.web.CallbackEnabled.extend( /** @lends openerp.web
var self = this;
// Construct a JSON-RPC2 request, method is currently unused
params.session_id = this.session_id;
if (this.debug)
params.debug = 1;
// Call using the rpc_mode
var deferred = $.Deferred();
@ -480,14 +481,12 @@ openerp.web.Session = openerp.web.CallbackEnabled.extend( /** @lends openerp.web
session_login: function(db, login, password, success_callback) {
var self = this;
var params = { db: db, login: login, password: password };
this.rpc("/web/session/login", params, function(result) {
return this.rpc("/web/session/login", params, function(result) {
self.session_id = result.session_id;
self.uid = result.uid;
self.user_context = result.context;
self.db = result.db;
self.session_save();
if (self.uid)
self.on_session_valid();
return true;
}).then(success_callback);
},
@ -529,7 +528,8 @@ openerp.web.Session = openerp.web.CallbackEnabled.extend( /** @lends openerp.web
* @param name the cookie's name
*/
get_cookie: function (name) {
var nameEQ = this.element_id + '|' + name + '=';
if (!this.name) { return null; }
var nameEQ = this.name + '|' + name + '=';
var cookies = document.cookie.split(';');
for(var i=0; i<cookies.length; ++i) {
var cookie = cookies[i].replace(/^\s*/, '');
@ -548,9 +548,11 @@ openerp.web.Session = openerp.web.CallbackEnabled.extend( /** @lends openerp.web
* @param ttl the cookie's time to live, 1 year by default, set to -1 to delete
*/
set_cookie: function (name, value, ttl) {
if (!this.name) { return; }
ttl = ttl || 24*60*60*365;
document.cookie = [
this.element_id + '|' + name + '=' + encodeURIComponent(JSON.stringify(value)),
this.name + '|' + name + '=' + encodeURIComponent(JSON.stringify(value)),
'path=/',
'max-age=' + ttl,
'expires=' + new Date(new Date().getTime() + ttl*1000).toGMTString()
].join(';');
@ -570,15 +572,11 @@ openerp.web.Session = openerp.web.CallbackEnabled.extend( /** @lends openerp.web
var file_list = ["/web/static/lib/datejs/globalization/" +
self.user_context.lang.replace("_", "-") + ".js"
];
if(self.debug) {
self.rpc('/web/webclient/csslist', {"mods": modules}, self.do_load_css);
self.rpc('/web/webclient/jslist', {"mods": modules}, function(files) {
self.do_load_js(file_list.concat(files));
});
} else {
self.do_load_css(["/web/webclient/css?mods="+modules]);
self.do_load_js(file_list.concat(["/web/webclient/js?mods="+modules]));
}
self.rpc('/web/webclient/csslist', {"mods": modules}, self.do_load_css);
self.rpc('/web/webclient/jslist', {"mods": modules}, function(files) {
self.do_load_js(file_list.concat(files));
});
openerp._modules_loaded = true;
});
});
@ -587,7 +585,7 @@ openerp.web.Session = openerp.web.CallbackEnabled.extend( /** @lends openerp.web
var self = this;
_.each(files, function (file) {
$('head').append($('<link>', {
'href': file + (self.debug ? '?debug=' + (new Date().getTime()) : ''),
'href': file,
'rel': 'stylesheet',
'type': 'text/css'
}));
@ -599,14 +597,15 @@ openerp.web.Session = openerp.web.CallbackEnabled.extend( /** @lends openerp.web
var file = files.shift();
var tag = document.createElement('script');
tag.type = 'text/javascript';
tag.src = file + (this.debug ? '?debug=' + (new Date().getTime()) : '');
tag.src = file;
tag.onload = tag.onreadystatechange = function() {
if ( (tag.readyState && tag.readyState != "loaded" && tag.readyState != "complete") || tag.onload_done )
return;
tag.onload_done = true;
self.do_load_js(files);
};
document.head.appendChild(tag);
var head = document.head || document.getElementsByTagName('head')[0];
head.appendChild(tag);
} else {
this.on_modules_loaded();
}
@ -1045,6 +1044,21 @@ openerp.web.TranslationDataBase = openerp.web.Class.extend(/** @lends openerp.we
});
openerp.web._t = new openerp.web.TranslationDataBase().build_translation_function();
openerp.web.qweb = new QWeb2.Engine();
openerp.web.qweb.debug = (window.location.search.indexOf('?debug') !== -1);
openerp.web.qweb.format_text_node = function(s) {
// Note that 'this' is the Qweb Node of the text
var translation = this.node.parentNode.attributes['t-translation'];
if (translation && translation.value === 'off') {
return s;
}
var ts = _.trim(s);
if (ts.length === 0) {
return s;
}
var tr = openerp.web._t(ts);
return tr === ts ? s : tr;
}
};

View File

@ -233,6 +233,7 @@ openerp.web.StaticDataGroup = openerp.web.GrouplessDataGroup.extend( /** @lends
});
openerp.web.DataSet = openerp.web.Widget.extend( /** @lends openerp.web.DataSet# */{
identifier_prefix: "dataset",
/**
* DateaManagement interface between views and the collection of selected
* OpenERP records (represents the view's state?)
@ -242,16 +243,12 @@ openerp.web.DataSet = openerp.web.Widget.extend( /** @lends openerp.web.DataSet
*
* @param {String} model the OpenERP model this dataset will manage
*/
init: function(source_controller, model, context) {
// we don't want the dataset to be a child of anything!
this._super(null);
this.session = source_controller ? source_controller.session : undefined;
init: function(parent, model, context) {
this._super(parent);
this.model = model;
this.context = context || {};
this.index = null;
},
start: function() {
},
previous: function () {
this.index -= 1;
if (this.index < 0) {
@ -266,6 +263,15 @@ openerp.web.DataSet = openerp.web.Widget.extend( /** @lends openerp.web.DataSet
}
return this;
},
select_id: function(id) {
var idx = _.indexOf(this.ids, id);
if (idx === -1) {
return false;
} else {
this.index = idx;
return true;
}
},
/**
* Read records.
*
@ -487,7 +493,7 @@ openerp.web.DataSetStatic = openerp.web.DataSet.extend({
offset = options.offset || 0,
limit = options.limit || false,
fields = fields || false;
var end_pos = limit && limit !== -1 ? offset + limit : undefined;
var end_pos = limit && limit !== -1 ? offset + limit : this.ids.length;
return this.read_ids(this.ids.slice(offset, end_pos), fields, callback);
},
set_ids: function (ids) {
@ -549,13 +555,11 @@ openerp.web.DataSetSearch = openerp.web.DataSet.extend(/** @lends openerp.web.D
sort: this.sort(),
offset: offset,
limit: options.limit || false
}, function (result) {
}).pipe(function (result) {
self.ids = result.ids;
self.offset = offset;
if (callback) {
callback(result.records);
}
});
return result.records;
}).then(callback);
},
get_domain: function (other_domain) {
if (other_domain) {
@ -603,20 +607,27 @@ openerp.web.DataSetSearch = openerp.web.DataSet.extend(/** @lends openerp.web.D
});
openerp.web.BufferedDataSet = openerp.web.DataSetStatic.extend({
virtual_id_prefix: "one2many_v_id_",
virtual_id_regex: /one2many_v_id_.*/,
debug_mode: true,
init: function() {
this._super.apply(this, arguments);
this.reset_ids([]);
this.last_default_get = {};
},
default_get: function(fields, callback) {
return this._super(fields).then(this.on_default_get).then(callback);
},
on_default_get: function(res) {
this.last_default_get = res;
},
create: function(data, callback, error_callback) {
var cached = {id:_.uniqueId(this.virtual_id_prefix), values: data};
this.to_create.push(cached);
var cached = {id:_.uniqueId(this.virtual_id_prefix), values: data,
defaults: this.last_default_get};
this.to_create.push(_.extend(_.clone(cached), {values: _.clone(cached.values)}));
this.cache.push(cached);
this.on_change();
var to_return = $.Deferred().then(callback);
to_return.resolve({result: cached.id});
return to_return.promise();
var prom = $.Deferred().then(callback);
prom.resolve({result: cached.id});
return prom.promise();
},
write: function (id, data, options, callback) {
var self = this;
@ -637,6 +648,10 @@ openerp.web.BufferedDataSet = openerp.web.DataSetStatic.extend({
self.to_write.push(record);
}
var cached = _.detect(this.cache, function(x) {return x.id === id;});
if (!cached) {
cached = {id: id, values: {}};
this.cache.push(cached);
}
$.extend(cached.values, record.values);
if (dirty)
this.on_change();
@ -676,7 +691,8 @@ openerp.web.BufferedDataSet = openerp.web.DataSetStatic.extend({
var cached = _.detect(self.cache, function(x) {return x.id === id;});
var created = _.detect(self.to_create, function(x) {return x.id === id;});
if (created) {
_.each(fields, function(x) {if (cached.values[x] === undefined) cached.values[x] = false;});
_.each(fields, function(x) {if (cached.values[x] === undefined)
cached.values[x] = created.defaults[x] || false;});
} else {
if (!cached || !_.all(fields, function(x) {return cached.values[x] !== undefined}))
to_get.push(id);
@ -692,7 +708,7 @@ openerp.web.BufferedDataSet = openerp.web.DataSetStatic.extend({
throw "Record not correctly loaded";
}
}
setTimeout(function () {completion.resolve(records);}, 0);
completion.resolve(records);
};
if(to_get.length > 0) {
var rpc_promise = this._super(to_get, fields, function(records) {
@ -715,23 +731,53 @@ openerp.web.BufferedDataSet = openerp.web.DataSetStatic.extend({
return completion.promise();
}
});
openerp.web.ReadOnlyDataSetSearch = openerp.web.DataSetSearch.extend({
openerp.web.BufferedDataSet.virtual_id_regex = /^one2many_v_id_.*$/;
openerp.web.ProxyDataSet = openerp.web.DataSetSearch.extend({
init: function() {
this._super.apply(this, arguments);
this.create_function = null;
this.write_function = null;
this.read_function = null;
},
read_ids: function () {
if (this.read_function) {
return this.read_function.apply(null, arguments);
} else {
return this._super.apply(this, arguments);
}
},
default_get: function(fields, callback) {
return this._super(fields, callback).then(this.on_default_get);
},
on_default_get: function(result) {},
create: function(data, callback, error_callback) {
this.on_create(data);
var to_return = $.Deferred().then(callback);
setTimeout(function () {to_return.resolve({"result": undefined});}, 0);
return to_return.promise();
if (this.create_function) {
return this.create_function(data, callback, error_callback);
} else {
console.warn("trying to create a record using default proxy dataset behavior");
var to_return = $.Deferred().then(callback);
setTimeout(function () {to_return.resolve({"result": undefined});}, 0);
return to_return.promise();
}
},
on_create: function(data) {},
write: function (id, data, options, callback) {
this.on_write(id, data);
var to_return = $.Deferred().then(callback);
setTimeout(function () {to_return.resolve({"result": true});}, 0);
return to_return.promise();
if (this.write_function) {
return this.write_function(id, data, options, callback);
} else {
console.warn("trying to write a record using default proxy dataset behavior");
var to_return = $.Deferred().then(callback);
setTimeout(function () {to_return.resolve({"result": true});}, 0);
return to_return.promise();
}
},
on_write: function(id, data) {},
unlink: function(ids, callback, error_callback) {
this.on_unlink(ids);
console.warn("trying to unlink a record using default proxy dataset behavior");
var to_return = $.Deferred().then(callback);
setTimeout(function () {to_return.resolve({"result": true});}, 0);
return to_return.promise();

View File

@ -0,0 +1,344 @@
openerp.web.data_import = function(openerp) {
var QWeb = openerp.web.qweb,
_t = openerp.web._t;
/**
* Safari does not deal well at all with raw JSON data being returned. As a
* result, we're going to cheat by using a pseudo-jsonp: instead of getting
* JSON data in the iframe, we're getting a ``script`` tag which consists of a
* function call and the returned data (the json dump).
*
* The function is an auto-generated name bound to ``window``, which calls
* back into the callback provided here.
*
* @param {Object} form the form element (DOM or jQuery) to use in the call
* @param {Object} attributes jquery.form attributes object
* @param {Function} callback function to call with the returned data
*/
function jsonp(form, attributes, callback) {
attributes = attributes || {};
var options = {jsonp: _.uniqueId('import_callback_')};
window[options.jsonp] = function () {
delete window[options.jsonp];
callback.apply(null, arguments);
};
if ('data' in attributes) {
_.extend(attributes.data, options);
} else {
_.extend(attributes, {data: options});
}
$(form).ajaxSubmit(attributes);
}
openerp.web.DataImport = openerp.web.Dialog.extend({
template: 'ImportDataView',
dialog_title: "Import Data",
init: function(parent, dataset){
var self = this;
this._super(parent, {});
this.model = parent.model;
this.fields = [];
this.all_fields = [];
this.fields_with_defaults = [];
this.required_fields = null;
var convert_fields = function (root, prefix) {
prefix = prefix || '';
_(root.fields).each(function (f) {
self.all_fields.push(prefix + f.name);
if (f.fields) {
convert_fields(f, prefix + f.id + '/');
}
});
};
this.ready = $.Deferred.queue().then(function () {
self.required_fields = _(self.fields).chain()
.filter(function (field) {
return field.required &&
!_.include(self.fields_with_defaults, field.id); })
.pluck('name')
.value();
convert_fields(self);
self.all_fields.sort();
});
},
start: function() {
var self = this;
this._super();
this.open({
modal: true,
width: '70%',
height: 'auto',
position: 'top',
buttons: [
{text: "Close", click: function() { self.stop(); }},
{text: "Import File", click: function() { self.do_import(); }, 'class': 'oe-dialog-import-button'}
],
close: function(event, ui) {
self.stop();
}
});
this.toggle_import_button(false);
this.$element.find('#csvfile').change(this.on_autodetect_data);
this.$element.find('fieldset').change(this.on_autodetect_data);
this.$element.find('fieldset legend').click(function() {
$(this).next().toggle();
});
this.ready.push(new openerp.web.DataSet(this, this.model).call(
'fields_get', [], function (fields) {
self.graft_fields(fields);
self.ready.push(new openerp.web.DataSet(self, self.model)
.default_get(_.pluck(self.fields, 'id'), function (fields) {
_.each(fields, function(val, key) {
if (val) {
self.fields_with_defaults.push(key);
}
});
})
)
}));
},
graft_fields: function (fields, parent, level) {
parent = parent || this;
level = level || 0;
var self = this;
if (level === 0) {
parent.fields.push({
id: 'id',
name: 'id',
string: _t('External ID'),
required: false
});
}
_(fields).each(function (field, field_name) {
if (field_name === 'id') { return; }
var f = {
id: field_name,
name: field_name,
string: field.string,
required: field.required
};
switch (field.type) {
case 'many2many':
case 'many2one':
f.name += '/id';
break;
case 'one2many':
f.name += '/id';
f.fields = [];
// only fetch sub-fields to a depth of 2 levels
if (level < 2) {
self.ready.push(new openerp.web.DataSet(self, field.relation).call(
'fields_get', [], function (fields) {
self.graft_fields(fields, f, level+1);
}));
}
break;
}
parent.fields.push(f);
});
},
toggle_import_button: function (newstate) {
this.$dialog.dialog('widget')
.find('.oe-dialog-import-button')
.button('option', 'disabled', !newstate);
},
do_import: function() {
if(!this.$element.find('#csvfile').val()) { return; }
var lines_to_skip = parseInt(this.$element.find('#csv_skip').val(), 10);
var with_headers = this.$element.find('#file_has_headers').prop('checked');
if (!lines_to_skip && with_headers) {
lines_to_skip = 1;
}
var indices = [], fields = [];
this.$element.find(".sel_fields").each(function(index, element) {
var val = element.value;
if (!val) {
return;
}
indices.push(index);
fields.push(val);
});
jsonp(this.$element.find('#import_data'), {
url: '/web/import/import_data',
data: {
model: this.model,
meta: JSON.stringify({
skip: lines_to_skip,
indices: indices,
fields: fields
})
}
}, this.on_import_results);
},
on_autodetect_data: function() {
if(!this.$element.find('#csvfile').val()) { return; }
jsonp(this.$element.find('#import_data'), {
url: '/web/import/detect_data'
}, this.on_import_results);
},
on_import_results: function(results) {
this.$element.find('#result').empty();
var headers, result_node = this.$element.find("#result");
if (results['records']) {
var lines_to_skip = parseInt(this.$element.find('#csv_skip').val(), 10),
with_headers = this.$element.find('#file_has_headers').prop('checked');
headers = with_headers ? results.records[0] : null;
result_node.append(QWeb.render('ImportView.result', {
'headers': headers,
'records': lines_to_skip ? results.records.slice(lines_to_skip)
: with_headers ? results.records.slice(1)
: results.records
}));
} else if (results['error']) {
result_node.append(QWeb.render('ImportView.error', {
'error': results['error']}));
} else if (results['success']) {
if (this.widget_parent.widget_parent.active_view == "list") {
this.widget_parent.reload_content();
}
this.stop();
return;
}
var self = this;
this.ready.then(function () {
var $fields = self.$element.find('.sel_fields').bind('blur', function () {
if (this.value && !_(self.all_fields).contains(this.value)) {
this.value = '';
}
}).autocomplete({
minLength: 0,
source: self.all_fields,
change: self.on_check_field_values
}).focus(function () {
$(this).autocomplete('search');
});
// Column auto-detection
_(headers).each(function (header, index) {
var field_name = self.match_column_to_field(header);
if (field_name) {
$fields.eq(index).val(field_name);
}
});
self.on_check_field_values();
});
},
/**
* Returns the name of the field (nested) matching the provided column name
*
* @param {String} name column name to look for
* @param {Array} [fields] fields to look into for the provided name
* @returns {String|undefined}
*/
match_column_to_field: function (name, fields) {
fields = fields || this.fields;
var f;
f = _(fields).detect(function (field) {
// TODO: levenshtein between header and field.string
return field.name === name
|| field.string.toLowerCase() === name.toLowerCase();
});
if (f) { return f.name; }
// if ``name`` is a path (o2m), we need to recurse through its .fields
var index = name.indexOf('/');
if (index === -1) { return undefined; }
// Get the first path section, try to find the matching field
var column_name = name.substring(0, index);
f = _(fields).detect(function (field) {
// field.name for o2m is $foo/id, so we want to match on id
return field.id === column_name
|| field.string.toLowerCase() === column_name.toLowerCase()
});
if (!f) { return undefined; }
// if we found a matching field for the first path section, recurse in
// its own .fields to try and get the rest of the path matched
var rest = this.match_column_to_field(
name.substring(index+1), f.fields);
if (!rest) { return undefined; }
return f.id + '/' + rest;
},
/**
* Looks through all the field selections, and tries to find if two
* (or more) columns were matched to the same model field.
*
* Returns a map of the multiply-mapped fields to an array of offending
* columns (not actually columns, but the inputs containing the same field
* names).
*
* Also has the side-effect of marking the discovered inputs with the class
* ``duplicate_fld``.
*
* @returns {Object<String, Array<String>>} map of duplicate field matches to same-valued inputs
*/
find_duplicate_fields: function() {
// Maps values to DOM nodes, in order to discover duplicates
var values = {}, duplicates = {};
this.$element.find(".sel_fields").each(function(index, element) {
var value = element.value;
var $element = $(element).removeClass('duplicate_fld');
if (!value) { return; }
if (!(value in values)) {
values[value] = element;
} else {
var same_valued_field = values[value];
if (value in duplicates) {
duplicates[value].push(element);
} else {
duplicates[value] = [same_valued_field, element];
}
$element.add(same_valued_field).addClass('duplicate_fld');
}
});
return duplicates;
},
on_check_field_values: function () {
this.$element.find("#message, #msg").remove();
var required_valid = this.check_required();
var duplicates = this.find_duplicate_fields();
if (_.isEmpty(duplicates)) {
this.toggle_import_button(required_valid);
} else {
var $err = $('<div id="msg" style="color: red;">Destination fields should only be selected once, some fields are selected more than once:</div>').insertBefore(this.$element.find('#result'));
var $dupes = $('<dl>').appendTo($err);
_(duplicates).each(function(elements, value) {
$('<dt>').text(value).appendTo($dupes);
_(elements).each(function(element) {
var cell = $(element).closest('td');
$('<dd>').text(cell.parent().children().index(cell)).appendTo($dupes);
});
});
this.toggle_import_button(false);
}
},
check_required: function() {
if (!this.required_fields.length) { return true; }
var selected_fields = _(this.$element.find('.sel_fields').get()).chain()
.pluck('value')
.compact()
.value();
var missing_fields = _.difference(this.required_fields, selected_fields);
if (missing_fields.length) {
this.$element.find("#result").before('<div id="message" style="color:red">*Required Fields are not selected : ' + missing_fields + '.</div>');
return false;
}
return true;
},
stop: function() {
$(this.$dialog).remove();
this._super();
}
});
};

View File

@ -28,10 +28,13 @@ openerp.web.format_value = function (value, descriptor, value_if_empty) {
case 'float':
var precision = descriptor.digits ? descriptor.digits[1] : 2;
var int_part = Math.floor(value);
var dec_part = Math.abs(Math.floor((value % 1) * Math.pow(10, precision)));
return _.sprintf('%d%s%d',
int_part,
openerp.web._t.database.parameters.decimal_point, dec_part);
var dec_part = _.sprintf(
'%.' + precision + 'f',
Math.abs(value) % 1).substring(2);
return _.sprintf('%d%s%s',
int_part,
openerp.web._t.database.parameters.decimal_point,
dec_part);
case 'float_time':
return _.sprintf("%02d:%02d",
Math.floor(value),
@ -69,6 +72,13 @@ openerp.web.format_value = function (value, descriptor, value_if_empty) {
} catch (e) {
return value.format("%H:%M:%S");
}
case 'selection':
// Each choice is [value, label]
var result = _(descriptor.selection).detect(function (choice) {
return choice[0] === value;
});
if (result) { return result[1]; }
return;
default:
return value;
}
@ -179,9 +189,13 @@ openerp.web.auto_date_to_str = function(value, type) {
* @param {String} [column.string] button label
* @param {String} [column.icon] button icon
* @param {String} [value_if_empty=''] what to display if the field's value is ``false``
* @param {Boolean} [process_modifiers=true] should the modifiers be computed ?
*/
openerp.web.format_cell = function (row_data, column, value_if_empty) {
var attrs = column.modifiers_for(row_data);
openerp.web.format_cell = function (row_data, column, value_if_empty, process_modifiers) {
var attrs = {};
if (process_modifiers !== false) {
attrs = column.modifiers_for(row_data);
}
if (attrs.invisible) { return ''; }
if (column.tag === 'button') {
return [

View File

@ -13,24 +13,35 @@ openerp.web.SearchView = openerp.web.Widget.extend(/** @lends openerp.web.Search
* @param view_id
* @param defaults
*/
init: function(parent, dataset, view_id, defaults) {
init: function(parent, dataset, view_id, defaults, hidden) {
this._super(parent);
this.dataset = dataset;
this.model = dataset.model;
this.view_id = view_id;
this.defaults = defaults || {};
this.has_defaults = !_.isEmpty(this.defaults);
this.inputs = [];
this.enabled_filters = [];
this.has_focus = false;
this.hidden = !!hidden;
this.headless = this.hidden && !this.has_defaults;
this.ready = $.Deferred();
},
start: function() {
this._super();
this.rpc("/web/searchview/load", {"model": this.model, "view_id":this.view_id}, this.on_loaded);
if (this.hidden) {
this.$element.hide();
}
if (this.headless) {
this.ready.resolve();
} else {
this.rpc("/web/searchview/load", {"model": this.model, "view_id":this.view_id}, this.on_loaded);
}
return this.ready.promise();
},
show: function () {
@ -105,8 +116,9 @@ openerp.web.SearchView = openerp.web.Widget.extend(/** @lends openerp.web.Search
*/
make_field: function (item, field) {
try {
return new (openerp.web.search.fields.get_object(field.type))
(item, field, this);
return new (openerp.web.search.fields.get_any(
[item.attrs.widget, field.type]))
(item, field, this);
} catch (e) {
if (! e instanceof openerp.web.KeyNotFound) {
throw e;
@ -137,10 +149,7 @@ openerp.web.SearchView = openerp.web.Widget.extend(/** @lends openerp.web.Search
'defaults': this.defaults
});
// We don't understand why the following commented line does not work in Chrome but
// the non-commented line does. As far as we investigated, only God knows.
//this.$element.html(render);
jQuery(render).appendTo(this.$element);
this.$element.html(render);
this.$element.find(".oe_search-view-custom-filter-btn").click(ext.on_activate);
var f = this.$element.find('form');
@ -246,10 +255,13 @@ openerp.web.SearchView = openerp.web.Widget.extend(/** @lends openerp.web.Search
* @param e jQuery event object coming from the "Search" button
*/
do_search: function (e) {
if (this.headless && !this.has_defaults) {
return this.on_search([], [], []);
}
// reset filters management
var select = this.$element.find(".oe_search-view-filters-management");
select.val("_filters");
if (e && e.preventDefault) { e.preventDefault(); }
var data = this.build_search_data();
@ -324,10 +336,10 @@ openerp.web.SearchView = openerp.web.Widget.extend(/** @lends openerp.web.Search
* @param {Array} errors a never-empty array of error objects
*/
on_invalid: function (errors) {
this.notification.notify("Invalid Search", "triggered from search view");
this.do_notify("Invalid Search", "triggered from search view");
},
do_clear: function () {
this.$element.find('.filter_label').removeClass('enabled');
this.$element.find('.filter_label, .filter_icon').removeClass('enabled');
this.enabled_filters.splice(0);
var string = $('a.searchview_group_string');
_.each(string, function(str){
@ -631,6 +643,12 @@ openerp.web.search.Field = openerp.web.search.Input.extend( /** @lends openerp.w
this.attrs = _.extend({}, field, view_section.attrs);
this.filters = new openerp.web.search.FilterGroup(_.map(
view_section.children, function (filter_node) {
if (filter_node.attrs.string &&
typeof console !== 'undefined' && console.debug) {
console.debug("Filter-in-field with a 'string' attribute "
+ "in view", view);
}
delete filter_node.attrs.string;
return new openerp.web.search.Filter(
filter_node, view);
}), view);
@ -748,9 +766,44 @@ openerp.web.search.FloatField = openerp.web.search.NumberField.extend(/** @lends
* @extends openerp.web.search.Field
*/
openerp.web.search.SelectionField = openerp.web.search.Field.extend(/** @lends openerp.web.search.SelectionField# */{
// This implementation is a basic <select> field, but it may have to be
// altered to be more in line with the GTK client, which uses a combo box
// (~ jquery.autocomplete):
// * If an option was selected in the list, behave as currently
// * If something which is not in the list was entered (via the text input),
// the default domain should become (`ilike` string_value) but **any
// ``context`` or ``filter_domain`` becomes falsy, idem if ``@operator``
// is specified. So at least get_domain needs to be quite a bit
// overridden (if there's no @value and there is no filter_domain and
// there is no @operator, return [[name, 'ilike', str_val]]
template: 'SearchView.field.selection',
init: function () {
this._super.apply(this, arguments);
// prepend empty option if there is no empty option in the selection list
this.prepend_empty = !_(this.attrs.selection).detect(function (item) {
return !item[1];
});
},
get_value: function () {
return this.$element.val();
var index = parseInt(this.$element.val(), 10);
if (isNaN(index)) { return null; }
var value = this.attrs.selection[index][0];
if (value === false) { return null; }
return value;
},
/**
* The selection field needs a default ``false`` value in case none is
* provided, so that selector options with a ``false`` value (convention
* for explicitly empty options) get selected by default rather than the
* first (value-holding) option in the selection.
*
* @param {Object} defaults search default values
*/
render: function (defaults) {
if (!defaults[this.attrs.name]) {
defaults[this.attrs.name] = false;
}
return this._super(defaults);
}
});
openerp.web.search.BooleanField = openerp.web.search.SelectionField.extend(/** @lends openerp.web.search.BooleanField# */{

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,5 @@
openerp.web.list = function (openerp) {
var _t = openerp.web._t;
var QWeb = openerp.web.qweb;
openerp.web.views.add('list', 'openerp.web.ListView');
openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView# */ {
@ -10,7 +11,7 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView#
// whether the column headers should be displayed
'header': true,
// display addition button, with that label
'addable': "New",
'addable': _t("New"),
// whether the list view can be sorted, note that once a view has been
// sorted it can not be reordered anymore
'sortable': true,
@ -49,6 +50,7 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView#
this.model = dataset.model;
this.view_id = view_id;
this.previous_colspan = null;
this.colors = null;
this.columns = [];
@ -75,6 +77,7 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView#
}
self.compute_aggregates();
});
},
/**
* Retrieves the view's number of records per page (|| section)
@ -131,6 +134,31 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView#
this.$element.addClass('oe-listview');
return this.reload_view(null, null, true);
},
/**
* Returns the color for the provided record in the current view (from the
* ``@colors`` attribute)
*
* @param {Record} record record for the current row
* @returns {String} CSS color declaration
*/
color_for: function (record) {
if (!this.colors) { return ''; }
var context = _.extend({}, record.attributes, {
uid: this.session.uid,
current_date: new Date().toString('yyyy-MM-dd')
// TODO: time, datetime, relativedelta
});
for(var i=0, len=this.colors.length; i<len; ++i) {
var pair = this.colors[i],
color = pair[0],
expression = pair[1];
if (py.evaluate(expression, context)) {
return 'color: ' + color + ';';
}
// TODO: handle evaluation errors
}
return '';
},
/**
* Called after loading the list view's description, sets up such things
* as the view table's columns, renders the table itself and hooks up the
@ -159,6 +187,17 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView#
this.fields_view = data;
this.name = "" + this.fields_view.arch.attrs.string;
if (this.fields_view.arch.attrs.colors) {
this.colors = _(this.fields_view.arch.attrs.colors.split(';')).chain()
.compact()
.map(function(color_pair) {
var pair = color_pair.split(':'),
color = pair[0],
expr = pair[1];
return [color, py.parse(py.tokenize(expr)), expr];
}).value();
}
this.setup_columns(this.fields_view.fields, grouped);
this.$element.html(QWeb.render("ListView", this));
@ -214,7 +253,7 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView#
'<option value="100">100</option>' +
'<option value="200">200</option>' +
'<option value="500">500</option>' +
'<option value="NaN">Unlimited</option>')
'<option value="NaN">' + _t("Unlimited") + '</option>')
.change(function () {
var val = parseInt($select.val(), 10);
self._limit = (isNaN(val) ? null : val);
@ -353,9 +392,6 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView#
if (this.sidebar) {
this.sidebar.$element.show();
}
if (!_(this.dataset.ids).isEmpty()) {
this.reload_content();
}
},
do_hide: function () {
this.$element.hide();
@ -404,41 +440,22 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView#
self.compute_aggregates();
}));
},
/**
* Event handler for a search, asks for the computation/folding of domains
* and contexts (and group-by), then reloads the view's content.
*
* @param {Array} domains a sequence of literal and non-literal domains
* @param {Array} contexts a sequence of literal and non-literal contexts
* @param {Array} groupbys a sequence of literal and non-literal group-by contexts
* @returns {$.Deferred} fold request evaluation promise
*/
do_search: function (domains, contexts, groupbys) {
return this.rpc('/web/session/eval_domain_and_context', {
domains: _([this.dataset.get_domain()].concat(domains)).compact(),
contexts: _([this.dataset.get_context()].concat(contexts)).compact(),
group_by_seq: groupbys
}, $.proxy(this, 'do_actual_search'));
},
/**
* Handler for the result of eval_domain_and_context, actually perform the
* searching
*
* @param {Object} results results of evaluating domain and process for a search
*/
do_actual_search: function (results) {
do_search: function (domain, context, group_by) {
this.groups.datagroup = new openerp.web.DataGroup(
this, this.model,
results.domain,
results.context,
results.group_by);
this, this.model, domain, context, group_by);
this.groups.datagroup.sort = this.dataset._sort;
if (_.isEmpty(results.group_by) && !results.context['group_by_no_leaf']) {
results.group_by = null;
if (_.isEmpty(group_by) && !context['group_by_no_leaf']) {
group_by = null;
}
this.reload_view(!!results.group_by, results.context).then(
this.reload_view(!!group_by, context).then(
$.proxy(this, 'reload_content'));
},
/**
@ -447,7 +464,7 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView#
* @param {Array} ids the ids of the records to delete
*/
do_delete: function (ids) {
if (!ids.length) {
if (!(ids.length && confirm(_t("Are you sure to remove those records ?")))) {
return;
}
var self = this;
@ -455,6 +472,7 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView#
_(ids).each(function (id) {
self.records.remove(self.records.get(id));
});
self.configure_pager(self.dataset);
self.compute_aggregates();
});
},
@ -467,7 +485,13 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView#
do_select: function (ids, records) {
this.$element.find('.oe-list-delete')
.attr('disabled', !ids.length);
if (this.sidebar) {
if (ids.length) {
this.sidebar.do_unfold();
} else {
this.sidebar.do_fold();
}
}
if (!records.length) {
this.compute_aggregates();
return;
@ -498,14 +522,8 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView#
* @param {openerp.web.DataSet} dataset dataset in which the record is available (may not be the listview's dataset in case of nested groups)
*/
do_activate_record: function (index, id, dataset) {
var self = this;
// TODO is it needed ?
this.dataset.read_slice([],{
context: dataset.get_context(),
domain: dataset.get_domain()
}, function () {
self.select_record(index);
});
this.dataset.ids = dataset.ids;
this.select_record(index);
},
/**
* Handles signal for the addition of a new record (can be a creation,
@ -604,7 +622,7 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView#
}
$footer_cells.filter(_.sprintf('[data-field=%s]', column.id))
.html(openerp.web.format_cell(aggregation, column));
.html(openerp.web.format_cell(aggregation, column, undefined, false));
});
},
get_selected_ids: function() {
@ -750,24 +768,71 @@ openerp.web.ListView.List = openerp.web.Class.extend( /** @lends openerp.web.Lis
$row = $target.closest('tr'),
record_id = self.row_id($row);
$(self).trigger('action', [field, record_id, function () {
// note: $.data converts data to number if it's composed only
// of digits, nice when storing actual numbers, not nice when
// storing strings composed only of digits. Force the action
// name to be a string
$(self).trigger('action', [field.toString(), record_id, function () {
return self.reload_record(self.records.get(record_id));
}]);
})
.delegate('tr', 'click', function (e) {
e.stopPropagation();
self.dataset.index = self.records.indexOf(
self.records.get(
self.row_id(e.currentTarget)));
self.row_clicked(e);
var row_id = self.row_id(e.currentTarget);
if (row_id !== undefined) {
if (!self.dataset.select_id(row_id)) {
throw "Could not find id in dataset"
}
self.row_clicked(e);
}
});
},
row_clicked: function () {
$(this).trigger(
'row_link',
[this.records.at(this.dataset.index).get('id'),
[this.dataset.ids[this.dataset.index],
this.dataset]);
},
render_cell: function (record, column) {
var value;
if(column.type === 'reference') {
value = record.get(column.id);
var ref_match;
// Ensure that value is in a reference "shape", otherwise we're
// going to loop on performing name_get after we've resolved (and
// set) a human-readable version. m2o does not have this issue
// because the non-human-readable is just a number, where the
// human-readable version is a pair
if (value && (ref_match = /([\w\.]+),(\d+)/.exec(value))) {
// reference values are in the shape "$model,$id" (as a
// string), we need to split and name_get this pair in order
// to get a correctly displayable value in the field
var model = ref_match[1],
id = parseInt(ref_match[2], 10);
new openerp.web.DataSet(this.view, model).name_get([id], function(names) {
if (!names.length) { return; }
record.set(column.id, names[0][1]);
});
}
} else if (column.type === 'many2one') {
value = record.get(column.id);
// m2o values are usually name_get formatted, [Number, String]
// pairs, but in some cases only the id is provided. In these
// cases, we need to perform a name_get call to fetch the actual
// displayable value
if (typeof value === 'number' || value instanceof Number) {
// fetch the name, set it on the record (in the right field)
// and let the various registered events handle refreshing the
// row
new openerp.web.DataSet(this.view, column.relation)
.name_get([value], function (names) {
if (!names.length) { return; }
record.set(column.id, names[0]);
});
}
}
return openerp.web.format_cell(record.toForm().data, column);
},
render: function () {
if (this.$current) {
this.$current.remove();
@ -775,7 +840,7 @@ openerp.web.ListView.List = openerp.web.Class.extend( /** @lends openerp.web.Lis
this.$current = this.$_element.clone(true);
this.$current.empty().append(
QWeb.render('ListView.rows', _.extend({
render_cell: openerp.web.format_cell}, this)));
render_cell: $.proxy(this, 'render_cell')}, this)));
this.pad_table_to(5);
},
pad_table_to: function (count) {
@ -799,7 +864,9 @@ openerp.web.ListView.List = openerp.web.Class.extend( /** @lends openerp.web.Lis
cells.push('</tr>');
var row = cells.join('');
this.$current.append(new Array(count - this.records.length + 1).join(row));
this.$current
.children('tr:not([data-id])').remove().end()
.append(new Array(count - this.records.length + 1).join(row));
this.refresh_zebra(this.records.length);
},
/**
@ -880,7 +947,8 @@ openerp.web.ListView.List = openerp.web.Class.extend( /** @lends openerp.web.Lis
options: this.options,
record: record,
row_parity: (index % 2 === 0) ? 'even' : 'odd',
render_cell: openerp.web.format_cell
view: this.view,
render_cell: $.proxy(this, 'render_cell')
});
},
/**
@ -1055,7 +1123,7 @@ openerp.web.ListView.Groups = openerp.web.Class.extend( /** @lends openerp.web.L
var group_column = _(self.columns).detect(function (column) {
return column.id === group.grouped_on; });
$group_column.html(openerp.web.format_cell(
row_data, group_column, "Undefined"
row_data, group_column, _t("Undefined")
));
if (group.openable) {
// Make openable if not terminal group & group_by_no_leaf
@ -1131,7 +1199,8 @@ openerp.web.ListView.Groups = openerp.web.Class.extend( /** @lends openerp.web.L
var fields = _.pluck(_.select(this.columns, function(x) {return x.tag == "field"}), 'name');
var options = { offset: page * limit, limit: limit };
dataset.read_slice(fields, options , function (records) {
//TODO xmo: investigate why we need to put the setTimeout
setTimeout(function() {dataset.read_slice(fields, options , function (records) {
if (!self.datagroup.openable) {
view.configure_pager(dataset);
} else {
@ -1150,7 +1219,7 @@ openerp.web.ListView.Groups = openerp.web.Class.extend( /** @lends openerp.web.L
self.records.add(records, {silent: true});
list.render();
d.resolve(list);
});
});}, 0);
return d.promise();
},
setup_resequence_rows: function (list, dataset) {
@ -1355,10 +1424,10 @@ var Record = openerp.web.Class.extend(/** @lends Record# */{
* @returns {Object} record displayable in a form view
*/
toForm: function () {
var form_data = {};
_(this.attributes).each(function (value, key) {
form_data[key] = {value: value};
});
var form_data = {}, attrs = this.attributes;
for(var k in attrs) {
form_data[k] = {value: attrs[k]};
}
return {data: form_data};
}

View File

@ -22,6 +22,7 @@ openerp.web.list_editable = function (openerp) {
if (self.groups.get_selection().length) {
return;
}
self.configure_pager(self.dataset);
self.compute_aggregates();
}
})
@ -56,11 +57,11 @@ openerp.web.list_editable = function (openerp) {
|| this.defaults.editable);
},
/**
* Replace do_actual_search to handle editability process
* Replace do_search to handle editability process
*/
do_actual_search: function (results) {
this.set_editable(results.context['set_editable']);
this._super(results);
do_search: function(domain, context, group_by) {
this.set_editable(context['set_editable']);
this._super.apply(this, arguments);
},
/**
* Replace do_add_record to handle editability (and adding new record
@ -120,6 +121,7 @@ openerp.web.list_editable = function (openerp) {
delete self.edition_id;
delete self.edition;
});
this.pad_table_to(5);
return cancelled.promise();
},
/**
@ -147,7 +149,7 @@ openerp.web.list_editable = function (openerp) {
var $new_row = $('<tr>', {
id: _.uniqueId('oe-editable-row-'),
'data-id': record_id,
'class': $(row).attr('class') + ' oe_forms',
'class': row ? $(row).attr('class') : '' + ' oe_forms',
click: function (e) {e.stopPropagation();}
})
.delegate('button.oe-edit-row-save', 'click', function () {
@ -173,14 +175,26 @@ openerp.web.list_editable = function (openerp) {
});
if (row) {
$new_row.replaceAll(row);
} else if (self.options.editable === 'top') {
self.$current.prepend($new_row);
} else if (self.options.editable) {
self.$current.append($new_row);
var $last_child = self.$current.children('tr:last');
if (self.records.length) {
if (self.options.editable === 'top') {
$new_row.insertBefore(
self.$current.children('[data-id]:first'));
} else {
$new_row.insertAfter(
self.$current.children('[data-id]:last'));
}
} else {
$new_row.prependTo(self.$current);
}
if ($last_child.is(':not([data-id])')) {
$last_child.remove();
}
}
self.edition = true;
self.edition_id = record_id;
self.edition_form = _.extend(new openerp.web.ListEditableFormView(self, self.dataset, false), {
self.edition_form = _.extend(new openerp.web.ListEditableFormView(self.view, self.dataset, false), {
form_template: 'ListView.row.form',
registry: openerp.web.list.form.widgets,
$element: $new_row
@ -325,11 +339,13 @@ openerp.web.list_editable = function (openerp) {
this.$element.children().css('visibility', '');
if (this.modifiers.tree_invisible) {
var old_invisible = this.invisible;
this.invisible = !!this.modifiers.tree_invisible;
this.invisible = true;
this._super();
this.invisible = old_invisible;
} else if (this.invisible) {
this.$element.children().css('visibility', 'hidden');
} else {
this._super();
}
}
});

View File

@ -32,6 +32,8 @@ openerp.web.TreeView = openerp.web.View.extend(/** @lends openerp.web.TreeView#
this.records = {};
this.options = _.extend({}, this.defaults, options || {});
_.bindAll(this, 'color_for');
},
start: function () {
@ -107,6 +109,43 @@ openerp.web.TreeView = openerp.web.View.extend(/** @lends openerp.web.TreeView#
$select.change();
}
});
if (!this.fields_view.arch.attrs.colors) {
return;
}
this.colors = _(this.fields_view.arch.attrs.colors.split(';')).chain()
.compact()
.map(function(color_pair) {
var pair = color_pair.split(':'),
color = pair[0],
expr = pair[1];
return [color, py.parse(py.tokenize(expr)), expr];
}).value();
},
/**
* Returns the color for the provided record in the current view (from the
* ``@colors`` attribute)
*
* @param {Object} record record for the current row
* @returns {String} CSS color declaration
*/
color_for: function (record) {
if (!this.colors) { return ''; }
var context = _.extend({}, record, {
uid: this.session.uid,
current_date: new Date().toString('yyyy-MM-dd')
// TODO: time, datetime, relativedelta
});
for(var i=0, len=this.colors.length; i<len; ++i) {
var pair = this.colors[i],
color = pair[0],
expression = pair[1];
if (py.evaluate(expression, context)) {
return 'color: ' + color + ';';
}
// TODO: handle evaluation errors
}
return '';
},
/**
* Sets up opening a row
@ -159,7 +198,8 @@ openerp.web.TreeView = openerp.web.View.extend(/** @lends openerp.web.TreeView#
'fields_view': self.fields_view.arch.children,
'fields': self.fields,
'level': $curr_node.data('level') || 0,
'render': openerp.web.format_value
'render': openerp.web.format_value,
'color_for': self.color_for
});
if ($curr_node.length) {

View File

@ -68,9 +68,11 @@ db.web.ActionManager = db.web.Widget.extend({
},
on_url_hashchange: function(url) {
var self = this;
self.rpc("/web/action/load", { action_id: url.action_id }, function(result) {
self.do_action(result.result);
});
if(url && url.action_id) {
self.rpc("/web/action/load", { action_id: url.action_id }, function(result) {
self.do_action(result.result);
});
}
},
do_action: function(action, on_close) {
var type = action.type.replace(/\./g,'_');
@ -86,7 +88,7 @@ db.web.ActionManager = db.web.Widget.extend({
console.log("Action manager can't handle action of type " + action.type, action);
return;
}
this[type](action, on_close);
return this[type](action, on_close);
},
ir_actions_act_window: function (action, on_close) {
if (action.target === 'new') {
@ -116,6 +118,15 @@ db.web.ActionManager = db.web.Widget.extend({
*/
},
ir_actions_act_window_close: function (action, on_closed) {
if (!this.dialog && on_closed) {
on_closed();
}
if (this.dialog && action.context) {
var model = action.context.active_model;
if (model === 'base.module.upgrade' || model === 'base.setup.installer' || model === 'base.module.upgrade') {
db.webclient.do_reload();
}
}
this.dialog_stop();
},
ir_actions_server: function (action, on_closed) {
@ -147,6 +158,9 @@ db.web.ActionManager = db.web.Widget.extend({
complete: $.unblockUI
});
});
},
ir_actions_act_url: function (action) {
window.open(action.url, action.target === 'self' ? '_self' : '_blank');
}
});
@ -163,9 +177,10 @@ db.web.ViewManager = db.web.Widget.extend(/** @lends db.web.ViewManager# */{
*/
init: function(parent, dataset, views) {
this._super(parent);
this.model = dataset.model;
this.model = dataset ? dataset.model : undefined;
this.dataset = dataset;
this.searchview = null;
this.last_search = false;
this.active_view = null;
this.views_src = _.map(views, function(x) {return x instanceof Array? {view_id: x[0], view_type: x[1]} : x;});
this.views = {};
@ -184,7 +199,6 @@ db.web.ViewManager = db.web.Widget.extend(/** @lends db.web.ViewManager# */{
start: function() {
this._super();
var self = this;
this.dataset.start();
this.$element.find('.oe_vm_switch button').click(function() {
self.on_mode_switch($(this).data('view-type'));
});
@ -225,35 +239,21 @@ db.web.ViewManager = db.web.Widget.extend(/** @lends db.web.ViewManager# */{
controller.set_embedded_view(view.embedded_view);
}
controller.do_switch_view.add_last(this.on_mode_switch);
if (view_type === 'list' && this.flags.search_view === false && this.action && this.action['auto_search']) {
// In case the search view is not instantiated: manually call ListView#search
var domains = !_(self.action.domain).isEmpty()
? [self.action.domain] : [],
contexts = !_(self.action.context).isEmpty()
? [self.action.context] : [];
controller.on_loaded.add({
callback: function () {
controller.do_search(domains, contexts, []);
},
position: 'last',
unique: true
});
}
var container = $("#" + this.element_id + '_view_' + view_type);
view_promise = controller.appendTo(container);
this.views[view_type].controller = controller;
$.when(view_promise).then(function() {
self.on_controller_inited(view_type, controller);
if (self.searchview && view.controller.searchable !== false) {
self.do_searchview_search();
}
});
this.views[view_type].controller = controller;
} else if (this.searchview && view.controller.searchable !== false) {
self.do_searchview_search();
}
if (this.searchview) {
if (view.controller.searchable === false) {
this.searchview.hide();
} else {
this.searchview.show();
}
this.searchview[(view.controller.searchable === false || this.searchview.hidden) ? 'hide' : 'show']();
}
this.$element
@ -273,14 +273,6 @@ db.web.ViewManager = db.web.Widget.extend(/** @lends db.web.ViewManager# */{
}
return view_promise;
},
/**
* Event launched when a controller has been inited.
*
* @param {String} view_type type of view
* @param {String} view the inited controller
*/
on_controller_inited: function(view_type, view) {
},
/**
* Sets up the current viewmanager's search view.
*
@ -294,14 +286,37 @@ db.web.ViewManager = db.web.Widget.extend(/** @lends db.web.ViewManager# */{
}
this.searchview = new db.web.SearchView(
this, this.dataset,
view_id, search_defaults);
view_id, search_defaults, this.flags.search_view === false);
this.searchview.on_search.add(function(domains, contexts, groupbys) {
var controller = self.views[self.active_view].controller;
controller.do_search.call(controller, domains, contexts, groupbys);
});
this.searchview.on_search.add(this.do_searchview_search);
return this.searchview.appendTo($("#" + this.element_id + "_search"));
},
do_searchview_search: function(domains, contexts, groupbys) {
var self = this,
controller = this.views[this.active_view].controller;
if (domains || contexts) {
this.rpc('/web/session/eval_domain_and_context', {
domains: [this.action.domain || []].concat(domains || []),
contexts: [this.action.context || {}].concat(contexts || []),
group_by_seq: groupbys || []
}, function (results) {
self.dataset.context = results.context;
self.dataset.domain = results.domain;
self.last_search = [results.domain, results.context, results.group_by];
controller.do_search(results.domain, results.context, results.group_by);
});
} else if (this.last_search) {
controller.do_search.apply(controller, this.last_search);
}
},
/**
* Event launched when a controller has been inited.
*
* @param {String} view_type type of view
* @param {String} view the inited controller
*/
on_controller_inited: function(view_type, view) {
},
/**
* Called when one of the view want to execute an action
*/
@ -332,6 +347,7 @@ db.web.ViewManagerAction = db.web.ViewManager.extend(/** @lends oepnerp.web.View
// dataset initialization will take the session from ``this``, so if we
// do not have it yet (and we don't, because we've not called our own
// ``_super()``) rpc requests will blow up.
this._super(parent, null, action.views);
this.session = parent.session;
this.action = action;
var dataset = new db.web.DataSetSearch(this, action.res_model, action.context, action.domain);
@ -339,7 +355,7 @@ db.web.ViewManagerAction = db.web.ViewManager.extend(/** @lends oepnerp.web.View
dataset.ids.push(action.res_id);
dataset.index = 0;
}
this._super(parent, dataset, action.views);
this.dataset = dataset;
this.flags = this.action.flags || {};
if (action.res_model == 'board.board' && action.views.length == 1 && action.views) {
// Not elegant but allows to avoid form chrome (pager, save/new
@ -360,28 +376,24 @@ db.web.ViewManagerAction = db.web.ViewManager.extend(/** @lends oepnerp.web.View
* launches an initial search after both views are done rendering.
*/
start: function() {
var self = this;
var self = this,
searchview_loaded,
search_defaults = {};
_.each(this.action.context, function (value, key) {
var match = /^search_default_(.*)$/.exec(key);
if (match) {
search_defaults[match[1]] = value;
}
});
// init search view
var searchview_id = this.action['search_view_id'] && this.action['search_view_id'][0];
var searchview_loaded;
if (this.flags.search_view !== false) {
var search_defaults = {};
_.each(this.action.context, function (value, key) {
var match = /^search_default_(.*)$/.exec(key);
if (match) {
search_defaults[match[1]] = value;
}
});
// init search view
var searchview_id = this.action['search_view_id'] && this.action['search_view_id'][0];
searchview_loaded = this.setup_search_view(
searchview_id || false, search_defaults);
}
searchview_loaded = this.setup_search_view(searchview_id || false, search_defaults);
var main_view_loaded = this._super();
var manager_ready = $.when(searchview_loaded, main_view_loaded);
if (searchview_loaded && this.action['auto_search']) {
if (searchview_loaded && this.action['auto_search'] !== false) {
// schedule auto_search
manager_ready.then(this.searchview.do_search);
}
@ -422,11 +434,16 @@ db.web.ViewManagerAction = db.web.ViewManager.extend(/** @lends oepnerp.web.View
on_mode_switch: function (view_type) {
var self = this;
return $.when(
this._super(view_type),
this.shortcut_check(this.views[view_type])).then(function () {
var active_controller = self.views[self.active_view].controller;
var view_id = active_controller.fields_view ? active_controller.fields_view.view_id : active_controller.view_id;
this._super(view_type),
this.shortcut_check(this.views[view_type])
).then(function() {
var controller = self.views[self.active_view].controller,
fvg = controller.fields_view,
view_id = (fvg && fvg.view_id) || '--';
self.$element.find('.oe_get_xml_view span').text(view_id);
if (!self.action.name && fvg) {
self.$element.find('.oe_view_title').text(fvg.arch.attrs.string || fvg.name);
}
});
},
shortcut_check : function(view) {
@ -471,7 +488,7 @@ db.web.ViewManagerAction = db.web.ViewManager.extend(/** @lends oepnerp.web.View
* Intercept do_action resolution from children views
*/
on_action_executed: function () {
new db.web.DataSet(this, 'res.log')
return new db.web.DataSet(this, 'res.log')
.call('get', [], this.do_display_log);
},
/**
@ -512,9 +529,57 @@ db.web.Sidebar = db.web.Widget.extend({
self.do_toggle();
});
},
call_default_on_sidebar: function(item) {
var func_name = 'on_sidebar_' + _.underscored(item.label);
var fn = this.widget_parent[func_name];
if(typeof fn === 'function') {
fn(item);
}
},
add_default_sections: function() {
this.add_section(_t('Customize'), 'customize');
this.add_items('customize', [
{
label: _t("Manage Views"),
callback: this.call_default_on_sidebar,
title: _t("Manage views of the current object"),
}, {
label: _t("Edit Workflow"),
callback: this.call_default_on_sidebar,
title: _t("Manage views of the current object"),
classname: 'oe_hide oe_sidebar_edit_workflow'
}, {
label: _t("Customize Object"),
callback: this.call_default_on_sidebar,
title: _t("Manage views of the current object"),
}
]);
this.add_section(_t('Other Options'), 'other');
this.add_items('other', [
{
label: _t("Import"),
callback: this.call_default_on_sidebar,
}, {
label: _t("Export"),
callback: this.call_default_on_sidebar,
}, {
label: _t("Translate"),
callback: this.call_default_on_sidebar,
classname: 'oe_sidebar_translate oe_hide'
}, {
label: _t("View Log"),
callback: this.call_default_on_sidebar,
classname: 'oe_hide oe_sidebar_view_log'
}
]);
},
add_toolbar: function(toolbar) {
var self = this;
_.each([['print', "Reports"], ['action', "Actions"], ['relate', "Links"]], function(type) {
_.each([['print', _t("Reports")], ['action', _t("Actions")], ['relate', _t("Links")]], function(type) {
var items = toolbar[type[0]];
if (items.length) {
for (var i = 0; i < items.length; i++) {
@ -524,15 +589,30 @@ db.web.Sidebar = db.web.Widget.extend({
classname: 'oe_sidebar_' + type[0]
}
}
self.add_section(type[0], type[1], items);
self.add_section(type[1], type[0]);
self.add_items(type[0], items);
}
});
},
add_section: function(code, name, items) {
// For each section, we pass a name/label and optionally an array of items.
// If no items are passed, then the section will be created as a custom section
// returning back an element_id to be used by a custom controller.
// Else, the section is a standard section with items displayed as links.
add_section: function(name, code) {
if(!code) code = _.underscored(name);
var $section = this.sections[code];
if(!$section) {
section_id = _.uniqueId(this.element_id + '_section_' + code + '_');
var $section = $(db.web.qweb.render("Sidebar.section", {
section_id: section_id,
name: name,
classname: 'oe_sidebar_' + code,
}));
$section.appendTo(this.$element.find('div.sidebar-actions'));
this.sections[code] = $section;
}
return $section;
},
add_items: function(section_code, items) {
// An item is a dictonary : {
// label: label to be displayed for the link,
// action: action to be launch when the link is clicked,
@ -541,25 +621,24 @@ db.web.Sidebar = db.web.Widget.extend({
// title: optional title for the link
// }
// Note: The item should have one action or/and a callback
//
var self = this,
section_id = _.uniqueId(this.element_id + '_section_' + code + '_');
$section = this.add_section(_.titleize(section_code.replace('_', ' ')), section_code),
section_id = $section.attr('id');
if (items) {
for (var i = 0; i < items.length; i++) {
items[i].element_id = _.uniqueId(section_id + '_item_');
this.items[items[i].element_id] = items[i];
}
}
var $section = $(db.web.qweb.render("Sidebar.section", {
section_id: section_id,
name: name,
classname: 'oe_sidebar_' + code,
items: items
}));
if (items) {
$section.find('a.oe_sidebar_action_a').click(function() {
var $items = $(db.web.qweb.render("Sidebar.section.items", {items: items}));
$items.find('a.oe_sidebar_action_a').click(function() {
var item = self.items[$(this).attr('id')];
if (item.callback) {
item.callback();
item.callback.apply(self, [item]);
}
if (item.action) {
var ids = self.widget_parent.get_selected_ids();
@ -589,10 +668,13 @@ db.web.Sidebar = db.web.Widget.extend({
}
return false;
});
var $ul = $section.find('ul');
if(!$ul.length) {
$ul = $('<ul/>').appendTo($section);
}
$items.appendTo($ul);
}
$section.appendTo(this.$element.find('div.sidebar-actions'));
this.sections[code] = $section;
return section_id;
},
do_fold: function() {
this.$element.addClass('closed-sidebar').removeClass('open-sidebar');
@ -771,32 +853,45 @@ db.web.View = db.web.Widget.extend(/** @lends db.web.View# */{
var self = this;
var result_handler = function () {
if (on_closed) { on_closed.apply(null, arguments); }
self.widget_parent.on_action_executed.apply(null, arguments);
if (self.widget_parent && self.widget_parent.on_action_executed) {
return self.widget_parent.on_action_executed.apply(null, arguments);
}
};
var context = new db.web.CompoundContext(dataset.get_context(), action_data.context || {});
var handler = function (r) {
var action = r.result;
if (action && action.constructor == Object) {
action.context = action.context || {};
_.extend(action.context, {
active_id: record_id || false,
active_ids: [record_id || false],
active_model: dataset.model
});
action.context = new db.web.CompoundContext(dataset.get_context(), action.context);
self.do_action(action, result_handler);
var ncontext = new db.web.CompoundContext(context);
if (record_id) {
ncontext.add({
active_id: record_id,
active_ids: [record_id],
active_model: dataset.model
});
}
ncontext.add(action.context || {});
return self.rpc('/web/session/eval_domain_and_context', {
contexts: [ncontext],
domains: []
}).pipe(function (results) {
action.context = results.context;
/* niv: previously we were overriding once more with action_data.context,
* I assumed this was not a correct behavior and removed it
*/
return self.do_action(action, result_handler);
}, null);
} else {
result_handler();
return result_handler();
}
};
var context = new db.web.CompoundContext(dataset.get_context(), action_data.context || {});
if (action_data.special) {
handler({result: {"type":"ir.actions.act_window_close"}});
return handler({result: {"type":"ir.actions.act_window_close"}});
} else if (action_data.type=="object") {
return dataset.call_button(action_data.name, [[record_id], context], handler);
} else if (action_data.type=="action") {
return this.rpc('/web/action/load', { action_id: parseInt(action_data.name, 10), context: context }, handler);
return this.rpc('/web/action/load', { action_id: parseInt(action_data.name, 10), context: context, do_not_eval: true}, handler);
} else {
return dataset.exec_workflow(record_id, action_data.name, handler);
}
@ -814,46 +909,17 @@ db.web.View = db.web.Widget.extend(/** @lends db.web.View# */{
},
do_switch_view: function(view) {
},
set_common_sidebar_sections: function(sidebar) {
sidebar.add_section('customize', "Customize", [
{
label: "Manage Views",
callback: this.on_sidebar_manage_view,
title: "Manage views of the current object"
}, {
label: "Edit Workflow",
callback: this.on_sidebar_edit_workflow,
title: "Manage views of the current object",
classname: 'oe_hide oe_sidebar_edit_workflow'
}, {
label: "Customize Object",
callback: this.on_sidebar_customize_object,
title: "Manage views of the current object"
}
]);
sidebar.add_section('other', "Other Options", [
{
label: "Import",
callback: this.on_sidebar_import
}, {
label: "Export",
callback: this.on_sidebar_export
}, {
label: "Translate",
callback: this.on_sidebar_translate,
classname: 'oe_sidebar_translate oe_hide'
}, {
label: "View Log",
callback: this.on_sidebar_view_log,
classname: 'oe_hide oe_sidebar_view_log'
}
]);
do_search: function(view) {
},
on_sidebar_manage_view: function() {
set_common_sidebar_sections: function(sidebar) {
sidebar.add_default_sections();
},
on_sidebar_manage_views: function() {
if (this.fields_view && this.fields_view.arch) {
$('<xmp>' + db.web.json_node_to_xml(this.fields_view.arch, true) + '</xmp>').dialog({ width: '95%', height: 600});
} else {
this.notification.warn("Manage Views", "Could not find current view declaration");
this.do_warn("Manage Views", "Could not find current view declaration");
}
},
on_sidebar_edit_workflow: function() {
@ -863,6 +929,8 @@ db.web.View = db.web.Widget.extend(/** @lends db.web.View# */{
console.log('Todo');
},
on_sidebar_import: function() {
var import_view = new db.web.DataImport(this, this.dataset);
import_view.start();
},
on_sidebar_export: function() {
var export_view = new db.web.DataExport(this, this.dataset);

View File

@ -2,9 +2,8 @@
<!-- vim:fdl=1:
-->
<templates id="template" xml:space="preserve">
<t t-name="Interface">
<div id="oe_loading" class="loading"></div>
<div id="oe_notification" class="oe_notification">
<t t-name="Notification">
<div class="oe_notification">
<div id="oe_notification_default">
<a class="ui-notify-cross ui-notify-close" href="#">x</a>
<h1>#{title}</h1>
@ -17,6 +16,9 @@
<p>#{text}</p>
</div>
</div>
</t>
<t t-name="Interface">
<div id="oe_loading" class="loading"></div>
<table border="0" cellpadding="0" cellspacing="0" width="100%" height="100%" class="main_table">
<tr>
<td colspan="2" valign="top">
@ -242,7 +244,23 @@
</table>
</form>
</t>
<t t-name="Login_dblist">
<select name="db">
<t t-foreach="db_list" t-as="db">
<t t-if="selected_db === db">
<option t-att-value="db" selected="true">
<t t-esc="db"/></option>
</t>
<t t-if="selected_db !== db">
<option t-att-value="db"><t t-esc="db"/></option>
</t>
</t>
</select>
</t>
<t t-name="Login">
<div>
<form class="oe_forms">
<fieldset>
<legend style="">
@ -253,33 +271,18 @@
<tr>
<td><label for="db">Database:</label></td>
<td>
<t t-if="!db_list">
<input type="text" name="db" t-att-value="selected_db || ''" autofocus="true"/>
</t>
<t t-if="db_list">
<select name="db">
<t t-foreach="db_list" t-as="db">
<t t-if="selected_db === db">
<option t-att-value="db" selected="true">
<t t-esc="db"/></option>
</t>
<t t-if="selected_db !== db">
<option t-att-value="db"><t t-esc="db"/></option>
</t>
</t>
</select>
</t>
<input type="text" name="db" t-att-value="widget.selected_db || ''" autofocus="true"/>
</td>
</tr>
<tr>
<td><label for="login">User:</label></td>
<td><input type="text" name="login"
t-att-value="selected_login || ''" autofocus="true"/></td>
t-att-value="widget.selected_login || ''" autofocus="true"/></td>
</tr>
<tr>
<td><label for="password">Password:</label></td>
<td><input type="password" name="password"
t-att-value="selected_password || ''"/></td>
t-att-value="widget.selected_password || ''"/></td>
</tr>
<tr>
<td></td>
@ -330,6 +333,7 @@
</table>
</div>
</div>
</t>
<t t-name="Header">
<div>
@ -445,11 +449,11 @@
</blockquote>
<a class="oe-shortcut-toggle" title="Add / Remove Shortcut..."
href="javascript: void(0)"> </a>
<h2 class="oe_view_title">
<t t-esc="self.action.name"/>
<button t-if="self.session.debug" class="oe_get_xml_view">
View#<span></span>
</button>
<button t-if="self.session.debug" class="oe_get_xml_view">
View#<span></span>
</button>
<h2 class="oe_view_title" t-if="self.flags.display_title !== false">
<t t-if="self.flags.display_title !== false" t-esc="self.action.name"/>
</h2>
</t>
<t t-jquery=".oe-view-manager-header" t-operation="after">
@ -465,17 +469,20 @@
</div>
</t>
<t t-name="Sidebar.section">
<h2><t t-esc="name"/></h2>
<div t-att-id="section_id" t-att-class="classname">
<ul t-if="items">
<h2><t t-esc="name"/></h2>
</div>
</t>
<t t-name="Sidebar.section.items">
<li t-foreach="items" t-as="item" t-att-class="item.classname">
<a class="oe_sidebar_action_a" t-att-id="item.element_id" t-att-title="item.title" href="#">
<t t-esc="item.label"/>
</a>
</li>
</ul>
</div>
</t>
<t t-name="TranslateDialog">
<ul class="oe_translate_tabs">
<li><a t-attf-href="##{widget.element_id}_fields">Fields</a></li>
@ -537,7 +544,7 @@
<td t-foreach="fields_view" t-as="field"
t-if="!field.attrs.modifiers.tree_invisible"
t-att-data-id="record.id"
t-att-style="!field_index ? 'background-position: ' + 19*level + 'px; padding-left: ' + 19*level + 'px' : undefined"
t-att-style="color_for(record) + (!field_index ? 'background-position: ' + 19*level + 'px; padding-left: ' + 19*level + 'px;' : '')"
t-att-class="!field_index and has_children ? 'treeview-tr' : 'treeview-td'">
<span t-if="!field.attrs.modifiers.invisible">
<t t-esc="render(record[field.attrs.name], fields[field.attrs.name])" />
@ -561,21 +568,7 @@
Delete
</button>
</td>
<th t-if="options.pager !== false" class="oe-list-pager">
<button type="button" disabled="disabled"
data-pager-action="first">First</button>
<button type="button" disabled="disabled"
data-pager-action="previous"
>&lt;</button>
<span class="oe-pager-state">
</span>
<button type="button" disabled="disabled"
data-pager-action="next">&gt;</button>
<button type="button" disabled="disabled"
data-pager-action="last">Last</button>
</th>
<t t-call="Listview.navigation.button"/>
</tr>
</table>
</th>
@ -605,8 +598,26 @@
</td>
<td t-if="options.deletable"/>
</tr>
<tr>
<t t-call="Listview.navigation.button"/>
</tr>
</tfoot>
</table>
<th t-name="Listview.navigation.button" t-if="options.pager !== false"
class="oe-list-pager" t-att-colspan="columns_count">
<button type="button" disabled="disabled"
data-pager-action="first">First</button>
<button type="button" disabled="disabled"
data-pager-action="previous">&lt;</button>
<span class="oe-pager-state">
</span>
<button type="button" disabled="disabled"
data-pager-action="next">&gt;</button>
<button type="button" disabled="disabled"
data-pager-action="last">Last</button>
</th>
<t t-name="ListView.rows" t-foreach="records.length" t-as="index">
<t t-call="ListView.row">
<t t-set="record" t-value="records.at(index)"/>
@ -614,7 +625,8 @@
</t>
</t>
<tr t-name="ListView.row" t-att-class="row_parity"
t-att-data-id="record.get('id')">
t-att-data-id="record.get('id')"
t-att-style="view.color_for(record)">
<t t-foreach="columns" t-as="column">
<td t-if="column.meta">
@ -628,7 +640,7 @@
<td t-if="!column.meta and column.invisible !== '1'" t-att-title="column.help"
t-att-class="'oe-field-cell' + (align ? ' oe-number' : '')"
t-att-data-field="column.id">
<t t-raw="render_cell(record.toForm().data, column)"/>
<t t-raw="render_cell(record, column)"/>
</td>
</t>
<td t-if="options.deletable" class='oe-record-delete' width="1">
@ -639,19 +651,15 @@
<t t-raw="frame.render()"/>
</t>
<t t-name="FormView">
<div class="oe_form_header" t-att-id="view.element_id + '_header'">
<div class="oe_form_header">
<div class="oe_form_buttons" t-if="view.options.action_buttons !== false">
<!--<button type="button" class="oe_form_button_save">
<button type="button" class="oe_form_button_save">
<span class="oe_form_on_update">Save</span>
<span class="oe_form_on_create">Create</span>
</button>-->
<button type="button" class="oe_form_button_save_edit">
<span class="oe_form_on_update">Save &amp; Edit</span>
<span class="oe_form_on_create">Create &amp; Edit</span>
</button>
<!--<button type="button" class="oe_form_button_cancel">Cancel</button>-->
<button type="button" class="oe_form_button_new">New</button>
<button type="button" class="oe_form_button_duplicate oe_form_on_update">Duplicate</button>
<button type="button" class="oe_form_button_toggle">Readonly/Editable</button>
</div>
<div class="oe_form_pager" t-if="view.options.pager !== false">
<button type="button" data-pager-action="first">First</button>
@ -711,8 +719,7 @@
t-att-width="td.width"
t-att-nowrap="td.nowrap or td.is_field_m2o? 'true' : undefined"
t-att-valign="td.table ? 'top' : undefined"
t-att-id="td.element_id"
t-attf-class="oe_form_frame_cell #{td.classname}"
t-attf-class="oe_form_frame_cell #{td.classname} #{td.element_class}"
>
<t t-raw="td.render()"/>
</td>
@ -722,8 +729,8 @@
</t>
<t t-name="WidgetNotebook">
<ul>
<li t-foreach="widget.pages" t-as="page" t-att-id="page.element_tab_id">
<a t-att-href="'#' + page.element_id">
<li t-foreach="widget.pages" t-as="page">
<a href="#">
<t t-esc="page.string"/>
</a>
</li>
@ -733,17 +740,23 @@
</t>
</t>
<t t-name="WidgetNotebookPage">
<div t-att-id="widget.element_id">
<div>
<t t-call="WidgetFrame"/>
</div>
</t>
<t t-name="WidgetNotebook.readonly">
<t t-foreach="widget.pages" t-as="page">
<h3><t t-esc="page.string"/></h3>
<t t-raw="page.render()"/>
</t>
</t>
<t t-name="WidgetSeparator">
<div t-if="widget.orientation !== 'vertical'" t-att-class="'separator ' + widget.orientation">
<t t-esc="widget.string"/>
</div>
</t>
<t t-name="WidgetLabel">
<label t-att-for="widget.element_id + '_field'"
<label t-att-for="widget.element_id"
t-att-class="'oe_label' + (widget.help ? '_help' : '')"
t-att-title="widget.help">
<t t-esc="widget.string"/>
@ -757,12 +770,22 @@
<t t-name="FieldChar">
<input type="text" size="1"
t-att-name="widget.name"
t-att-id="widget.element_id + '_field'"
t-att-class="'field_' + widget.type"
t-att-id="widget.element_id"
t-attf-class="field_#{widget.type}"
t-attf-style="width: #{widget.field.translate ? '99' : '100'}%"
/>
<img class="oe_field_translate" t-if="widget.field.translate" src="/web/static/src/img/icons/terp-translate.png" width="16" height="16" border="0"/>
</t>
<t t-name="FieldChar.readonly">
<div
t-att-id="widget.element_id"
t-attf-class="field_#{widget.type}"
t-attf-style="width: #{widget.field.translate ? '99' : '100'}%">
</div>
</t>
<t t-name="FieldURI.readonly">
<a href="#">#</a>
</t>
<t t-name="FieldEmail">
<table cellpadding="0" cellspacing="0" border="0" width="100%">
<tr>
@ -794,8 +817,8 @@
<t t-name="FieldText">
<textarea rows="6"
t-att-name="widget.name"
t-att-id="widget.element_id + '_field'"
t-att-class="'field_' + widget.type"
t-att-id="widget.element_id"
t-attf-class="field_#{widget.type}"
t-attf-style="width: #{widget.field.translate ? '99' : '100'}%"
></textarea>
<img class="oe_field_translate" t-if="widget.field.translate" src="/web/static/src/img/icons/terp-translate.png" width="16" height="16" border="0"/>
@ -814,8 +837,8 @@
<t t-name="FieldSelection">
<select
t-att-name="widget.name"
t-att-id="widget.element_id + '_field'"
t-att-class="'field_' + widget.type"
t-att-id="widget.element_id"
t-attf-class="field_#{widget.type}"
style="width: 100%">
<t t-foreach="widget.values" t-as="option">
<option><t t-esc="option[1]"/></option>
@ -823,9 +846,10 @@
</select>
</t>
<t t-name="FieldMany2One">
<div t-att-id="widget.element_id" class="oe-m2o">
<input t-att-id="widget.element_id + '_input'" type="text" size="1" style="width: 100%;"/>
<span class="oe-m2o-drop-down-button" t-att-id="widget.element_id + '_drop_down'">
<div class="oe-m2o">
<input type="text" size="1" style="width: 100%;"
t-att-id="widget.element_id"/>
<span class="oe-m2o-drop-down-button">
<img src="/web/static/src/img/down-arrow.png" /></span>
<span class="oe-m2o-cm-button" t-att-id="widget.name + '_open'">
<img src="/web/static/src/img/icons/gtk-index.png"/></span>
@ -848,8 +872,6 @@
</ul>
</t>
<t t-name="FieldOne2Many">
<div t-att-id="widget.element_id">
</div>
</t>
<t t-name="FieldMany2Many">
<div t-att-id="widget.list_id"></div>
@ -857,10 +879,10 @@
<t t-name="FieldReference">
<table border="0" width="100%" cellpadding="0" cellspacing="0" class="oe_frame oe_forms">
<tr>
<td t-att-id="widget.selection.element_id" class="oe_form_frame_cell oe_form_selection">
<td t-attf-class="oe_form_frame_cell oe_form_selection #{widget.selection.element_class}">
<t t-raw="widget.selection.render()"/>
</td>
<td t-att-id="widget.m2o.element_id" class="oe_form_frame_cell oe_form_many2one" nowrap="true">
<td t-attf-class="oe_form_frame_cell oe_form_many2one #{widget.m2o.element_class}" nowrap="true" style="display: none">
<t t-raw="widget.m2o.render()"/>
</td>
</tr>
@ -869,8 +891,8 @@
<t t-name="FieldBoolean">
<input type="checkbox"
t-att-name="widget.name"
t-att-id="widget.element_id + '_field'"
t-att-class="'field_' + widget.type"/>
t-att-id="widget.element_id"
t-attf-class="field_#{widget.type}"/>
</t>
<t t-name="FieldProgressBar">
<div t-opentag="true" class="oe-progressbar">
@ -885,7 +907,7 @@
t-att-border="widget.readonly ? 0 : 1"
t-att-id="widget.element_id + '_field'"
t-att-name="widget.name"
t-att-class="'field_' + widget.type"
t-attf-class="field_#{widget.type}"
t-att-width="widget.node.attrs.img_width || widget.node.attrs.width"
t-att-height="widget.node.attrs.img_height || widget.node.attrs.height"
/>
@ -933,7 +955,7 @@
<input type="text" size="1"
t-att-name="widget.name"
t-att-id="widget.element_id + '_field'"
t-att-class="'field_' + widget.type" style="width: 100%"
t-attf-class="field_#{widget.type}" style="width: 100%"
/>
</td>
<td class="oe-binary" nowrap="true">
@ -978,7 +1000,6 @@
</t>
<t t-name="WidgetButton">
<button type="button"
t-att-id="widget.element_id + '_button'"
t-att-title="widget.help"
style="width: 100%" class="button">
<img t-if="widget.node.attrs.icon" t-att-src="'/web/static/src/img/icons/' + widget.node.attrs.icon + '.png'" width="16" height="16"/>
@ -1075,14 +1096,14 @@
<div style="white-space: nowrap;">
<select t-att-name="attrs.name" t-att-id="element_id"
t-att-autofocus="attrs.default_focus === '1' || undefined">
<option/>
<option t-if="prepend_empty"/>
<t t-foreach="attrs.selection" t-as="option">
<t t-set="selected" t-value="defaults[attrs.name] === option[0]"/>
<option t-if="selected"
t-att-value="option[0]" selected="selected">
t-att-value="option_index" selected="selected">
<t t-esc="option[1]"/>
</option>
<option t-if="!selected" t-att-value="option[0]">
<option t-if="!selected" t-att-value="option_index">
<t t-esc="option[1]"/>
</option>
</t>
@ -1383,6 +1404,79 @@
</table>
</form>
</t>
<t t-name="ImportView">
<a id="importview" href="javascript: void(0)" style="text-decoration: none;color: #3D3D3D;">Import</a>
</t>
<t t-name="ImportDataView">
<form name="import_data" id="import_data" action="" method="post" enctype="multipart/form-data">
<input type="hidden" name="session_id" t-att-value="session.session_id"/>
<h2 class="separator horizontal">1. Import a .CSV file</h2>
<p>Select a .CSV file to import. If you need a sample of file to import,
you should use the export tool with the "Import Compatible" option.
</p>
<p>
<label for="csvfile">CSV File:</label>
<input type="file" id="csvfile" size="50" name="csvfile"/>
</p>
<h2 class="separator horizontal">2. Check your file format</h2>
<div id="result"></div>
<fieldset>
<legend style="cursor:pointer;">Import Options</legend>
<table style="display:none">
<tr>
<td colspan="4">
<label for="file_has_headers">Does your file have titles?</label>
<input type="checkbox" checked="checked"
id="file_has_headers"/>
</td>
</tr>
<tr>
<td><label for="csv_separator">Separator:</label></td>
<td><input type="text" name="csvsep" id="csv_separator" value=","/></td>
<td><label for="csv_delimiter">Delimiter:</label></td>
<td><input type="text" name="csvdel" id="csv_delimiter" value='"'/></td>
</tr>
<tr>
<td><label for="csv_encoding">Encoding:</label></td>
<td>
<select name="csvcode" id="csv_encoding">
<option value="utf-8">UTF-8</option>
<option value="latin1">Latin 1</option>
</select>
</td>
<td><label for="csv_skip" title="For use if CSV files have titles on multiple lines, skips more than a single line during import">
Lines to skip<sup>?</sup>:</label></td>
<td><input type="number" id="csv_skip" value="0" min="0"/></td>
</tr>
</table>
</fieldset>
</form>
</t>
<table t-name="ImportView.result"
class="oe_import_grid" width="100%" style="margin: 5px 0;">
<tr t-if="headers" class="oe_import_grid-header">
<td t-foreach="headers" t-as="header" class="oe_import_grid-cell">
<t t-esc="header"/></td>
</tr>
<tr>
<td t-foreach="records[0]" t-as="column">
<input class="sel_fields"/>
</td>
</tr>
<tr t-foreach="records" t-as="record" class="oe_import_grid-row">
<td t-foreach="record" t-as="cell" class="oe_import_grid-cell">
<t t-esc="cell"/></td>
</tr>
</table>
<t t-name="ImportView.error">
<p style="white-space:pre-line;">The import failed due to:<t t-esc="error.message"/></p>
<t t-if="error.preview">
<p>Here is a preview of the file we could not import:</p>
<pre><t t-esc="error.preview"/></pre>
</t>
</t>
<t t-name="About-Page">
<div>
<h1>OpenERP Web</h1>

View File

@ -27,6 +27,18 @@ $(document).ready(function () {
var fl = 12.1234;
var str = openerp.web.format_value(fl, {type:"float"});
equal(str, "12.12");
equal(openerp.web.format_value(12.02, {type: 'float'}),
'12.02');
equal(openerp.web.format_value(0.0002, {type: 'float', digits: [1, 3]}),
'0.000');
equal(openerp.web.format_value(0.0002, {type: 'float', digits: [1, 4]}),
'0.0002');
equal(openerp.web.format_value(0.0002, {type: 'float', digits: [1, 6]}),
'0.000200');
equal(openerp.web.format_value(1, {type: 'float', digits: [1, 6]}),
'1.000000');
equal(openerp.web.format_value(1, {type: 'float'}),
'1.00');
});
test("parse_datetime", function () {
var val = openerp.web.str_to_datetime("2009-05-04 12:34:23");
@ -51,4 +63,4 @@ $(document).ready(function () {
var val = openerp.web.parse_value(str, {type:"float"});
equal(val, -134112.1234);
});
});
});

View File

@ -21,7 +21,7 @@
<script src="/web/static/lib/datejs/sugarpak.js"></script>
<script src="/web/static/lib/datejs/extras.js"></script>
<script src="/web/static/lib/qweb/qweb.js"></script>
<script src="/web/static/lib/qweb/qweb2.js"></script>
<script src="/web/static/src/js/boot.js"></script>
<script src="/web/static/src/js/core.js"></script>
@ -31,11 +31,8 @@
<script src="/web/static/src/js/data.js"></script>
<script src="/web/static/src/js/views.js"></script>
<script src="/web/static/src/js/search.js"></script>
<script src="/web/static/src/js/form.js"></script>
<script src="/web/static/src/js/list.js"></script>
<script type="text/javascript">
QWeb.add_template('/web/static/src/xml/web.xml');
</script>
<script src="/web/static/src/js/view_form.js"></script>
<script src="/web/static/src/js/view_list.js"></script>
</head>
<body id="oe" class="openerp">
<h1 id="qunit-header">OpenERP web Test Suite</h1>

View File

@ -1,5 +1,6 @@
{
"name": "web calendar",
"category" : "Hidden",
"version": "2.0",
"depends": ['web'],
"js": [

View File

@ -0,0 +1,22 @@
# Danish translation for openerp-web
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openerp-web package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-10-07 10:38+0200\n"
"PO-Revision-Date: 2011-10-11 13:57+0000\n"
"Last-Translator: Jonas Mortensen <Unknown>\n"
"Language-Team: Danish <da@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-10-12 04:44+0000\n"
"X-Generator: Launchpad (build 14124)\n"
#: addons/web_calendar/static/src/xml/web_calendar.xml:0
msgid "&nbsp;"
msgstr "&nbsp;"

View File

@ -0,0 +1,22 @@
# German translation for openerp-web
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openerp-web package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-10-07 10:38+0200\n"
"PO-Revision-Date: 2011-10-10 12:36+0000\n"
"Last-Translator: Felix Schubert <Unknown>\n"
"Language-Team: German <de@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-10-11 05:42+0000\n"
"X-Generator: Launchpad (build 14123)\n"
#: addons/web_calendar/static/src/xml/web_calendar.xml:0
msgid "&nbsp;"
msgstr "&nbsp;"

View File

@ -0,0 +1,22 @@
# Spanish translation for openerp-web
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openerp-web package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-10-07 10:38+0200\n"
"PO-Revision-Date: 2011-10-18 10:41+0000\n"
"Last-Translator: Amós Oviedo <Unknown>\n"
"Language-Team: Spanish <es@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-10-19 06:05+0000\n"
"X-Generator: Launchpad (build 14157)\n"
#: addons/web_calendar/static/src/xml/web_calendar.xml:0
msgid "&nbsp;"
msgstr "&nbsp;"

View File

@ -0,0 +1,22 @@
# Spanish (Ecuador) translation for openerp-web
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openerp-web package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-10-07 10:38+0200\n"
"PO-Revision-Date: 2011-10-07 15:54+0000\n"
"Last-Translator: Cristian Salamea (Gnuthink) <ovnicraft@gmail.com>\n"
"Language-Team: Spanish (Ecuador) <es_EC@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-10-08 05:30+0000\n"
"X-Generator: Launchpad (build 14110)\n"
#: addons/web_calendar/static/src/xml/web_calendar.xml:0
msgid "&nbsp;"
msgstr "&nbsp;"

View File

@ -0,0 +1,22 @@
# Estonian translation for openerp-web
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openerp-web package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-10-07 10:38+0200\n"
"PO-Revision-Date: 2011-10-10 19:20+0000\n"
"Last-Translator: Aare Vesi <Unknown>\n"
"Language-Team: Estonian <et@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-10-11 05:42+0000\n"
"X-Generator: Launchpad (build 14123)\n"
#: addons/web_calendar/static/src/xml/web_calendar.xml:0
msgid "&nbsp;"
msgstr "&nbsp;"

View File

@ -0,0 +1,22 @@
# French translation for openerp-web
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openerp-web package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-10-07 10:38+0200\n"
"PO-Revision-Date: 2011-10-23 12:12+0000\n"
"Last-Translator: fhe (OpenERP) <Unknown>\n"
"Language-Team: French <fr@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-10-24 05:18+0000\n"
"X-Generator: Launchpad (build 14185)\n"
#: addons/web_calendar/static/src/xml/web_calendar.xml:0
msgid "&nbsp;"
msgstr "&nbsp;"

View File

@ -0,0 +1,22 @@
# Galician translation for openerp-web
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openerp-web package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-10-07 10:38+0200\n"
"PO-Revision-Date: 2011-10-19 10:25+0000\n"
"Last-Translator: Amós Oviedo <Unknown>\n"
"Language-Team: Galician <gl@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-10-20 04:48+0000\n"
"X-Generator: Launchpad (build 14165)\n"
#: addons/web_calendar/static/src/xml/web_calendar.xml:0
msgid "&nbsp;"
msgstr "&nbsp;"

View File

@ -0,0 +1,22 @@
# Italian translation for openerp-web
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openerp-web package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-10-07 10:38+0200\n"
"PO-Revision-Date: 2011-10-08 13:39+0000\n"
"Last-Translator: Nicola Riolini - Micronaet <Unknown>\n"
"Language-Team: Italian <it@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-10-09 05:22+0000\n"
"X-Generator: Launchpad (build 14110)\n"
#: addons/web_calendar/static/src/xml/web_calendar.xml:0
msgid "&nbsp;"
msgstr "&nbsp;"

View File

@ -0,0 +1,22 @@
# Dutch (Belgium) translation for openerp-web
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openerp-web package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-10-07 10:38+0200\n"
"PO-Revision-Date: 2011-10-07 09:05+0000\n"
"Last-Translator: Niels Huylebroeck <Unknown>\n"
"Language-Team: Dutch (Belgium) <nl_BE@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-10-08 05:30+0000\n"
"X-Generator: Launchpad (build 14110)\n"
#: addons/web_calendar/static/src/xml/web_calendar.xml:0
msgid "&nbsp;"
msgstr "&nbsp;"

View File

@ -0,0 +1,22 @@
# Slovak translation for openerp-web
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openerp-web package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-10-07 10:38+0200\n"
"PO-Revision-Date: 2011-10-23 14:42+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Slovak <sk@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-10-24 05:18+0000\n"
"X-Generator: Launchpad (build 14185)\n"
#: addons/web_calendar/static/src/xml/web_calendar.xml:0
msgid "&nbsp;"
msgstr ""

View File

@ -0,0 +1,22 @@
# Slovenian translation for openerp-web
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openerp-web package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-10-07 10:38+0200\n"
"PO-Revision-Date: 2011-10-19 06:26+0000\n"
"Last-Translator: Anze (Neotek) <Unknown>\n"
"Language-Team: Slovenian <sl@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-10-20 04:48+0000\n"
"X-Generator: Launchpad (build 14165)\n"
#: addons/web_calendar/static/src/xml/web_calendar.xml:0
msgid "&nbsp;"
msgstr "&nbsp;"

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2011-09-06 12:02+0200\n"
"POT-Creation-Date: 2011-10-07 10:38+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"

View File

@ -3,6 +3,7 @@
*---------------------------------------------------------*/
openerp.web_calendar = function(openerp) {
var _t = openerp.web._t;
var QWeb = openerp.web.qweb;
QWeb.add_template('/web_calendar/static/src/xml/web_calendar.xml');
openerp.web.views.add('calendar', 'openerp.web_calendar.CalendarView');
@ -13,16 +14,13 @@ openerp.web_calendar.CalendarView = openerp.web.View.extend({
this.set_default_options(options);
this.dataset = dataset;
this.model = dataset.model;
this.fields_view = {};
this.view_id = view_id;
this.domain = this.dataset.domain || [];
this.context = this.dataset.context || {};
this.has_been_loaded = $.Deferred();
this.creating_event_id = null;
this.dataset_events = [];
if (this.options.action_views_ids.form) {
this.form_dialog = new openerp.web_calendar.CalendarFormDialog(this, {}, this.options.action_views_ids.form, dataset);
this.form_dialog.start();
}
this.form_dialog = new openerp.web_calendar.CalendarFormDialog(this, {}, this.options.action_views_ids.form, dataset);
this.form_dialog.start();
this.COLOR_PALETTE = ['#f57900', '#cc0000', '#d400a8', '#75507b', '#3465a4', '#73d216', '#c17d11', '#edd400',
'#fcaf3e', '#ef2929', '#ff00c9', '#ad7fa8', '#729fcf', '#8ae234', '#e9b96e', '#fce94f',
'#ff8e00', '#ff0000', '#b0008c', '#9000ff', '#0078ff', '#00ff00', '#e6ff00', '#ffff00',
@ -31,10 +29,11 @@ openerp.web_calendar.CalendarView = openerp.web.View.extend({
},
start: function() {
this._super();
this.rpc("/web/view/load", {"model": this.model, "view_id": this.view_id, "view_type":"calendar", 'toolbar': true}, this.on_loaded);
return this.rpc("/web/view/load", {"model": this.model, "view_id": this.view_id, "view_type":"calendar", 'toolbar': true}, this.on_loaded);
},
stop: function() {
scheduler.clearAll();
this._super();
},
on_loaded: function(data) {
this.fields_view = data;
@ -46,6 +45,10 @@ openerp.web_calendar.CalendarView = openerp.web.View.extend({
this.name = this.fields_view.name || this.fields_view.arch.attrs.string;
this.view_id = this.fields_view.view_id;
// mode, one of month, week or day
this.mode = this.fields_view.arch.attrs.mode;
// date_start is mandatory, date_delay and date_stop are optional
this.date_start = this.fields_view.arch.attrs.date_start;
this.date_delay = this.fields_view.arch.attrs.date_delay;
this.date_stop = this.fields_view.arch.attrs.date_stop;
@ -54,6 +57,10 @@ openerp.web_calendar.CalendarView = openerp.web.View.extend({
this.day_length = this.fields_view.arch.attrs.day_length || 8;
this.color_field = this.fields_view.arch.attrs.color;
this.fields = this.fields_view.fields;
if (!this.date_start) {
throw new Error("Calendar view has not defined 'date_start' attribute.");
}
//* Calendar Fields *
this.calendar_fields.date_start = {'name': this.date_start, 'kind': this.fields[this.date_start].type};
@ -67,9 +74,6 @@ openerp.web_calendar.CalendarView = openerp.web.View.extend({
if (this.date_stop) {
this.calendar_fields.date_stop = {'name': this.date_stop, 'kind': this.fields[this.date_stop].type};
}
if (!this.date_delay && !this.date_stop) {
throw new Error("Calendar view has none of the following attributes : 'date_stop', 'date_delay'");
}
for (var fld = 0; fld < this.fields_view.arch.children.length; fld++) {
this.info_fields.push(this.fields_view.arch.children[fld].attrs.name);
@ -79,8 +83,8 @@ openerp.web_calendar.CalendarView = openerp.web.View.extend({
if (this.options.sidebar && this.options.sidebar_id) {
this.sidebar = new openerp.web.Sidebar(this, this.options.sidebar_id);
this.sidebar.start();
this.sidebar.navigator = new openerp.web_calendar.SidebarNavigator(this.sidebar, this.sidebar.add_section('navigator', "Navigator"), this);
this.sidebar.responsible = new openerp.web_calendar.SidebarResponsible(this.sidebar, this.sidebar.add_section('responsible', "Responsible"), this);
this.sidebar.navigator = new openerp.web_calendar.SidebarNavigator(this.sidebar, this);
this.sidebar.responsible = new openerp.web_calendar.SidebarResponsible(this.sidebar, this);
this.sidebar.add_toolbar(this.fields_view.toolbar);
this.set_common_sidebar_sections(this.sidebar);
this.sidebar.do_unfold();
@ -91,9 +95,6 @@ openerp.web_calendar.CalendarView = openerp.web.View.extend({
this.init_scheduler();
this.has_been_loaded.resolve();
if (this.dataset.ids.length) {
this.dataset.read_ids(this.dataset.ids, _.keys(this.fields), this.on_events_loaded);
}
},
init_scheduler: function() {
var self = this;
@ -110,9 +111,7 @@ openerp.web_calendar.CalendarView = openerp.web.View.extend({
scheduler.config.drag_resize = true;
scheduler.config.drag_create = true;
// Initialize Sceduler
this.mode = this.mode || 'month';
scheduler.init('openerp_scheduler', null, this.mode);
scheduler.init('openerp_scheduler', null, this.mode || 'month');
scheduler.detachAllEvents();
scheduler.attachEvent('onEventAdded', this.do_create_event);
@ -157,7 +156,9 @@ openerp.web_calendar.CalendarView = openerp.web.View.extend({
for (var e = 0; e < events.length; e++) {
var evt = events[e];
if (!evt[this.date_start]) {
this.notification.warn("Start date is not defined for event :", evt['id']);
if (this.session.debug) {
this.do_warn("Start date is not defined for event :", evt['id']);
}
break;
}
@ -182,10 +183,10 @@ openerp.web_calendar.CalendarView = openerp.web.View.extend({
}
if (this.fields[this.date_start]['type'] == 'date') {
evt[this.date_start] = openerp.web.str_to_date(evt[this.date_start]).set({hour: 9}).toString('yyyy-MM-dd HH:mm:ss');
evt[this.date_start] = openerp.web.auto_str_to_date(evt[this.date_start]).set({hour: 9}).toString('yyyy-MM-dd HH:mm:ss');
}
if (this.date_stop && evt[this.date_stop] && this.fields[this.date_stop]['type'] == 'date') {
evt[this.date_stop] = openerp.web.str_to_date(evt[this.date_stop]).set({hour: 17}).toString('yyyy-MM-dd HH:mm:ss');
evt[this.date_stop] = openerp.web.auto_str_to_date(evt[this.date_stop]).set({hour: 17}).toString('yyyy-MM-dd HH:mm:ss');
}
res_events.push(this.convert_event(evt));
}
@ -199,7 +200,7 @@ openerp.web_calendar.CalendarView = openerp.web.View.extend({
convert_event: function(evt) {
var date_start = openerp.web.str_to_datetime(evt[this.date_start]),
date_stop = this.date_stop ? openerp.web.str_to_datetime(evt[this.date_stop]) : null,
date_delay = evt[this.date_delay] || null,
date_delay = evt[this.date_delay] || 1.0,
res_text = '',
res_description = [];
@ -268,12 +269,14 @@ openerp.web_calendar.CalendarView = openerp.web.View.extend({
}
},
do_edit_event: function(event_id) {
var self = this;
event_id = parseInt(event_id, 10);
var index = _.indexOf(this.dataset.ids, event_id);
if (index > -1) {
this.dataset.index = index;
this.form_dialog.form.do_show();
this.form_dialog.open();
this.form_dialog.form.do_show().then(function() {
self.form_dialog.open();
});
return false;
}
return true;
@ -292,26 +295,17 @@ openerp.web_calendar.CalendarView = openerp.web.View.extend({
}
return data;
},
do_search: function(domains, contexts, groupbys) {
do_search: function(domain, context, group_by) {
var self = this;
scheduler.clearAll();
$.when(this.has_been_loaded).then(function() {
self.rpc('/web/session/eval_domain_and_context', {
domains: domains,
contexts: contexts,
group_by_seq: groupbys
}, function (results) {
// TODO: handle non-empty results.group_by with read_group
self.dataset.context = self.context = results.context;
self.dataset.domain = self.domain = results.domain;
self.dataset.read_slice(_.keys(self.fields), {
offset:0,
limit: self.limit
}, function(events) {
self.dataset_events = events;
self.on_events_loaded(events);
}
);
// TODO: handle non-empty results.group_by with read_group
self.dataset.read_slice(_.keys(self.fields), {
offset: 0,
limit: self.limit
}, function(events) {
self.dataset_events = events;
self.on_events_loaded(events);
});
});
},
@ -371,13 +365,16 @@ openerp.web_calendar.CalendarFormDialog = openerp.web.Dialog.extend({
});
openerp.web_calendar.SidebarResponsible = openerp.web.Widget.extend({
init: function(parent, element_id, view) {
this._super(parent, element_id);
init: function(parent, view) {
var $section = parent.add_section(_t('Responsible'), 'responsible');
this.$div = $('<div></div>');
$section.append(this.$div);
this._super(parent, $section.attr('id'));
this.view = view;
this.$element.delegate('input:checkbox', 'change', this.on_filter_click);
},
on_events_loaded: function(filters) {
this.$element.html(QWeb.render('CalendarView.sidebar.responsible', { filters: filters }));
this.$div.html(QWeb.render('CalendarView.sidebar.responsible', { filters: filters }));
},
on_filter_click: function(e) {
var responsibles = [],
@ -397,8 +394,9 @@ openerp.web_calendar.SidebarResponsible = openerp.web.Widget.extend({
});
openerp.web_calendar.SidebarNavigator = openerp.web.Widget.extend({
init: function(parent, element_id, view) {
this._super(parent, element_id);
init: function(parent, view) {
var $section = parent.add_section(_t('Navigator'), 'navigator');
this._super(parent, $section.attr('id'));
this.view = view;
},
on_events_loaded: function(events) {

View File

@ -1,5 +1,6 @@
{
"name": "Web Chat",
"category" : "Hidden",
"version": "2.0",
"depends": ['web'],
"js": [
@ -10,6 +11,6 @@
'static/src/js/web_chat.js'
],
"css": [],
# 'active': True,
'active': False,
'installable': False,
}

View File

@ -2,7 +2,7 @@
import time
import simplejson
import web.common as openerpweb
import web.common.http as openerpweb
import logging
_logger = logging.getLogger(__name__)

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2011-09-06 12:03+0200\n"
"POT-Creation-Date: 2011-10-07 10:39+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"

View File

@ -1,5 +1,6 @@
{
"name": "web Dashboard",
"category" : "Hidden",
"version": "2.0",
"depends": ['web'],
"js": [

View File

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
import web.common as openerpweb
import web.common.http as openerpweb
WIDGET_CONTENT_PATTERN = """<!DOCTYPE html>
<html>
@ -24,5 +24,5 @@ class Widgets(openerpweb.Controller):
@openerpweb.httprequest
def content(self, request, widget_id):
return WIDGET_CONTENT_PATTERN % request.session.model('res.widget').read(
[widget_id], ['content'], request.session.eval_context(request.context)
[int(widget_id)], ['content'], request.session.eval_context(request.context)
)[0]

View File

@ -0,0 +1,46 @@
# Danish translation for openerp-web
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openerp-web package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-10-07 10:39+0200\n"
"PO-Revision-Date: 2011-10-11 13:59+0000\n"
"Last-Translator: Jonas Mortensen <Unknown>\n"
"Language-Team: Danish <da@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-10-12 04:44+0000\n"
"X-Generator: Launchpad (build 14124)\n"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Reset"
msgstr "Nulstil"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Undo"
msgstr "Fortryd"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Add Widget"
msgstr "Tilføj widget"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Change layout"
msgstr "Skift layout"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Choose dashboard layout"
msgstr "Vælg layout for kontrolpanel"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "progress:"
msgstr "fremskridt:"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "%"
msgstr "%"

View File

@ -0,0 +1,46 @@
# German translation for openerp-web
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openerp-web package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-10-07 10:39+0200\n"
"PO-Revision-Date: 2011-10-10 12:38+0000\n"
"Last-Translator: Felix Schubert <Unknown>\n"
"Language-Team: German <de@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-10-11 05:42+0000\n"
"X-Generator: Launchpad (build 14123)\n"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Reset"
msgstr "Zurücksetzen"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Undo"
msgstr "Rückgängig"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Add Widget"
msgstr "Widget hinzufügen"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Change layout"
msgstr "Layout wechseln"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Choose dashboard layout"
msgstr "Wählen Sie das Dashboard Layout"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "progress:"
msgstr "Fortschritt:"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "%"
msgstr "%"

View File

@ -0,0 +1,46 @@
# Spanish translation for openerp-web
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openerp-web package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-10-07 10:39+0200\n"
"PO-Revision-Date: 2011-10-18 10:44+0000\n"
"Last-Translator: Amós Oviedo <Unknown>\n"
"Language-Team: Spanish <es@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-10-19 06:05+0000\n"
"X-Generator: Launchpad (build 14157)\n"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Reset"
msgstr "Reiniciar"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Undo"
msgstr "Deshacer"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Add Widget"
msgstr "Añadir Widget"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Change layout"
msgstr "Cambiar disposición"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Choose dashboard layout"
msgstr "Cambiar disposición del tablero"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "progress:"
msgstr "progreso:"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "%"
msgstr "%"

View File

@ -0,0 +1,46 @@
# Spanish (Ecuador) translation for openerp-web
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openerp-web package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-10-07 10:39+0200\n"
"PO-Revision-Date: 2011-10-07 15:56+0000\n"
"Last-Translator: Cristian Salamea (Gnuthink) <ovnicraft@gmail.com>\n"
"Language-Team: Spanish (Ecuador) <es_EC@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-10-08 05:30+0000\n"
"X-Generator: Launchpad (build 14110)\n"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Reset"
msgstr "Reset"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Undo"
msgstr "Deshacer"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Add Widget"
msgstr "Agregar Widget"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Change layout"
msgstr "Cambiar disposición"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Choose dashboard layout"
msgstr "Elegir el diseño del panel de control"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "progress:"
msgstr "progreso:"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "%"
msgstr "%"

View File

@ -0,0 +1,46 @@
# Estonian translation for openerp-web
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openerp-web package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-10-07 10:39+0200\n"
"PO-Revision-Date: 2011-10-10 19:29+0000\n"
"Last-Translator: Aare Vesi <Unknown>\n"
"Language-Team: Estonian <et@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-10-11 05:42+0000\n"
"X-Generator: Launchpad (build 14123)\n"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Reset"
msgstr "Lähtesta"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Undo"
msgstr "Ennista"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Add Widget"
msgstr ""
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Change layout"
msgstr ""
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Choose dashboard layout"
msgstr ""
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "progress:"
msgstr ""
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "%"
msgstr "%"

View File

@ -0,0 +1,46 @@
# French translation for openerp-web
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openerp-web package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-10-07 10:39+0200\n"
"PO-Revision-Date: 2011-10-23 12:11+0000\n"
"Last-Translator: Xavier (Open ERP) <Unknown>\n"
"Language-Team: French <fr@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-10-24 05:18+0000\n"
"X-Generator: Launchpad (build 14185)\n"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Reset"
msgstr ""
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Undo"
msgstr "Annuler"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Add Widget"
msgstr "Ajouter un Gadget"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Change layout"
msgstr "Changer la mise en page"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Choose dashboard layout"
msgstr "Choisissez la mise en page du tableau de bord"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "progress:"
msgstr "progrès"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "%"
msgstr "%"

View File

@ -0,0 +1,46 @@
# Galician translation for openerp-web
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openerp-web package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-10-07 10:39+0200\n"
"PO-Revision-Date: 2011-10-19 10:29+0000\n"
"Last-Translator: Amós Oviedo <Unknown>\n"
"Language-Team: Galician <gl@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-10-20 04:48+0000\n"
"X-Generator: Launchpad (build 14165)\n"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Reset"
msgstr "Reiniciar"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Undo"
msgstr "Desfacer"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Add Widget"
msgstr "Engadir un widget"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Change layout"
msgstr "Cambiar disposición"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Choose dashboard layout"
msgstr "Cambiar disposición do taboleiro"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "progress:"
msgstr "progreso:"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "%"
msgstr "%"

View File

@ -0,0 +1,46 @@
# Italian translation for openerp-web
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openerp-web package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-10-07 10:39+0200\n"
"PO-Revision-Date: 2011-10-07 09:00+0000\n"
"Last-Translator: Davide Corio - agilebg.com <davide.corio@agilebg.com>\n"
"Language-Team: Italian <it@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-10-08 05:30+0000\n"
"X-Generator: Launchpad (build 14110)\n"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Reset"
msgstr "Ripristina"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Undo"
msgstr "Annulla"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Add Widget"
msgstr "Aggiungi Widget"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Change layout"
msgstr "Cambia layout"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Choose dashboard layout"
msgstr "Scegli layout dashboard"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "progress:"
msgstr "avanzamento:"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "%"
msgstr "%"

View File

@ -0,0 +1,46 @@
# Dutch (Belgium) translation for openerp-web
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openerp-web package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-10-07 10:39+0200\n"
"PO-Revision-Date: 2011-10-07 09:04+0000\n"
"Last-Translator: Niels Huylebroeck <Unknown>\n"
"Language-Team: Dutch (Belgium) <nl_BE@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-10-08 05:30+0000\n"
"X-Generator: Launchpad (build 14110)\n"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Reset"
msgstr "Reset"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Undo"
msgstr "Ongedaan maken"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Add Widget"
msgstr "Widget toevoegen"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Change layout"
msgstr "Layout aanpassen"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Choose dashboard layout"
msgstr "Dashboard layout kiezen"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "progress:"
msgstr "vooruitgang:"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "%"
msgstr "%"

View File

@ -0,0 +1,46 @@
# Slovak translation for openerp-web
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openerp-web package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-10-07 10:39+0200\n"
"PO-Revision-Date: 2011-10-23 14:45+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Slovak <sk@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-10-24 05:18+0000\n"
"X-Generator: Launchpad (build 14185)\n"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Reset"
msgstr ""
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Undo"
msgstr ""
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Add Widget"
msgstr ""
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Change layout"
msgstr ""
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Choose dashboard layout"
msgstr ""
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "progress:"
msgstr ""
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "%"
msgstr ""

View File

@ -0,0 +1,46 @@
# Slovenian translation for openerp-web
# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
# This file is distributed under the same license as the openerp-web package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2011-10-07 10:39+0200\n"
"PO-Revision-Date: 2011-10-19 06:25+0000\n"
"Last-Translator: Anze (Neotek) <Unknown>\n"
"Language-Team: Slovenian <sl@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2011-10-20 04:48+0000\n"
"X-Generator: Launchpad (build 14165)\n"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Reset"
msgstr "Ponastavi"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Undo"
msgstr "Razveljavi"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Add Widget"
msgstr "Dodaj gradnik"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Change layout"
msgstr "Spreminjanje postavitve"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "Choose dashboard layout"
msgstr "Izberite postavitev nadzorne plošče"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "progress:"
msgstr "napredek:"
#: addons/web_dashboard/static/src/xml/web_dashboard.xml:0
msgid "%"
msgstr "%"

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2011-09-06 12:02+0200\n"
"POT-Creation-Date: 2011-10-07 10:39+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"

View File

@ -7,17 +7,38 @@
}
.openerp .oe-dashboard-action {
margin: 0 0.5em 0.5em 0;
padding: 2px;
}
.openerp .oe-dashboard-action:hover {
border: 1px dashed #ccc;
padding: 1px;
padding: 0px;
background-color: white;
border-radius: 3px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
}
.openerp .oe-dashboard-action .oe-dashboard-action-header {
font-size: 125%;
font-size: 85%;
font-weight: bold;
text-transform: uppercase;
text-indent: 10px;
vertical-align: center;
border-bottom: 1px solid #e5e5e5;
background: white url("/web/static/src/img/box-a-header-a.gif") 0% 0% repeat-x;
}
.openerp h2.oe-dashboard-action-header {
margin: 0;
padding:4px 4px;
-moz-border-radius-topleft: 3px;
-webkit-border-top-left-radius: 3px;
border-top-left-radius: 3px;
-moz-border-radius-topright: 3px;
-webkit-border-top-right-radius: 3px;
border-top-right-radius: 3px;
}
.openerp h2.oe-dashboard-action-header-empty {
padding-top: 0;
padding-bottom: 2px;
}
.openerp a.oe-dashboard-action-rename {
float: left;
padding-right: 4px;
@ -57,6 +78,12 @@
visibility: hidden;
}
/* Base overwriting */
.openerp .oe-dashboard .oe-listview-content, .openerp .oe-dashboard .ui-widget-header {
border:none !important;
padding:0px 3px;
}
/* Layouts */
.openerp .oe-dashboard-layout_1 .oe-dashboard-column.index_0 {
width: 100%;
@ -234,6 +261,46 @@
.openerp .oe-dashboard-action .view-manager-main-content {
padding: 2px;
}
.openerp .oe-dashboard-action-header .ui-icon, .openerp .oe-dashboard-action-header .oe-dashboard-action-rename {
display: none;
.oe-static-home {
padding: 0.5em 0.5em;
text-align: center;
}
.oe-static-home h1 {
margin: 0 0 0.3em
}
.oe-static-home-banner {
display: inline-block;
margin: auto 0;
padding: 0.5em 5em;
text-align: left;
}
.oe-static-home-banner li {
font-size: 150%;
font-weight: bold;
}
.oe-static-home address {
font-style: normal;
padding-left: 2em;
}
.oe-static-home-tiles {
text-align: left;
}
.oe-static-home-tiles td {
vertical-align: top;
}
.oe-static-home-tile {
margin: 0.5em;
padding: 0 1em;
}
.oe-static-home-tile-logo {
margin-right: 0.5em;
}
.oe-static-home-tile-text h2 {
margin-top: 0;
margin-bottom: 0.2em;
}
.oe-static-home-tile-text p {
margin: 0.5em 0;
}

View File

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

View File

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

View File

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

View File

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

View File

Before

Width:  |  Height:  |  Size: 8.3 KiB

After

Width:  |  Height:  |  Size: 8.3 KiB

View File

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

View File

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

View File

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

@ -2,6 +2,11 @@ openerp.web_dashboard = function(openerp) {
var QWeb = openerp.web.qweb;
QWeb.add_template('/web_dashboard/static/src/xml/web_dashboard.xml');
if (!openerp.web_dashboard) {
/** @namespace */
openerp.web_dashboard = {};
}
openerp.web.form.DashBoard = openerp.web.form.Widget.extend({
init: function(view, node) {
this._super(view, node);
@ -43,9 +48,6 @@ openerp.web.form.DashBoard = openerp.web.form.Widget.extend({
});
//this.$element.find('a.oe-dashboard-action-rename').live('click', this.on_rename);
this.$element.find('.oe-dashboard-action').live('mouseover mouseout', function(event) {
$(this).find('.oe-dashboard-action-header .ui-icon, .oe-dashboard-action-header .oe-dashboard-action-rename').toggle(event.type == 'mouseover');
});
},
on_undo: function() {
this.rpc('/web/view/undo_custom', {
@ -217,6 +219,8 @@ openerp.web.form.DashBoard = openerp.web.form.Widget.extend({
});
},
on_load_action: function(result) {
var self = this;
var action_orig = _.extend({}, result.result);
var action = result.result;
action.flags = {
search_view : false,
@ -224,12 +228,21 @@ openerp.web.form.DashBoard = openerp.web.form.Widget.extend({
views_switcher : false,
action_buttons : false,
pager: false,
low_profile: true
low_profile: true,
display_title: false
};
var am = new openerp.web.ActionManager(this);
this.action_managers.push(am);
am.appendTo($("#"+this.view.element_id + '_action_' + action.id));
am.do_action(action);
am.do_action = function(action) {
self.do_action(action);
}
if (am.inner_viewmanager) {
am.inner_viewmanager.on_mode_switch.add(function(mode) {
self.do_action(action_orig);
});
}
},
render: function() {
// We should start with three columns available
@ -243,12 +256,10 @@ openerp.web.form.DashBoard = openerp.web.form.Widget.extend({
return QWeb.render(this.template, this);
},
do_reload: function() {
_.each(this.action_managers, function(am) {
am.stop();
});
this.action_managers = [];
var view_manager = this.view.widget_parent,
action_manager = view_manager.widget_parent;
this.view.stop();
this.view.start();
action_manager.do_action(view_manager.action);
}
});
openerp.web.form.DashBoardLegacy = openerp.web.form.DashBoard.extend({
@ -279,20 +290,19 @@ openerp.web.form.widgets.add('hpaned', 'openerp.web.form.DashBoardLegacy');
openerp.web.form.widgets.add('vpaned', 'openerp.web.form.DashBoardLegacy');
openerp.web.form.widgets.add('board', 'openerp.web.form.DashBoard');
openerp.web.client_actions.add(
'board.config.overview', 'openerp.web_dashboard.ConfigOverview'
);
if (!openerp.web_dashboard) {
/** @namespace */
openerp.web_dashboard = {};
}
/*
* ConfigOverview
* This client action designed to be used as a dashboard widget display
* ir.actions.todo in a fancy way
*/
openerp.web.client_actions.add( 'board.config.overview', 'openerp.web_dashboard.ConfigOverview');
openerp.web_dashboard.ConfigOverview = openerp.web.View.extend({
template: 'ConfigOverview',
init: function (parent) {
this._super(parent);
this.dataset = new openerp.web.DataSetSearch(
this, 'ir.actions.todo');
this.dataset.domain = [['type', '=', 'manual']];
this.dataset.domain = [['type', '!=', 'automatic']];
},
start: function () {
this._super();
@ -301,7 +311,7 @@ openerp.web_dashboard.ConfigOverview = openerp.web.View.extend({
.then(this.on_records_loaded);
},
on_records_loaded: function (read_response, progress_response) {
var records = read_response[0].records,
var records = read_response,
progress = progress_response[0];
var grouped_todos = _(records).chain()
@ -348,35 +358,146 @@ openerp.web_dashboard.ConfigOverview = openerp.web.View.extend({
}
});
openerp.web.client_actions.add(
'board.home.applications', 'openerp.web_dashboard.ApplicationTiles');
/*
* ApplicationTiles
* This client action designed to be used as a dashboard widget display
* either a list of application to install (if none is installed yet) or
* a list of root menu
*/
openerp.web.client_actions.add( 'board.home.applications', 'openerp.web_dashboard.ApplicationTiles');
openerp.web_dashboard.apps = {
applications: [
[
{
module: 'crm', name: 'CRM',
help: "Acquire leads, follow opportunities, manage prospects and phone calls, \u2026"
}, {
module: 'sale', name: 'Sales',
help: "Do quotations, follow sales orders, invoice and control deliveries"
}, {
module: 'account_voucher', name: 'Invoicing',
help: "Send invoice, track payments and reminders"
}, {
module: 'point_of_sale', name: 'Point of Sales',
help: "Manage shop sales, use touch-screen POS"
}
], [
{
module: 'purchase', name: 'Purchase',
help: "Do purchase orders, control invoices and reception, follow your suppliers, \u2026"
}, {
module: 'stock', name: 'Warehouse',
help: "Track your stocks, schedule product moves, manage incoming and outgoing shipments, \u2026"
}, {
module: 'mrp', name: 'Manufacturing',
help: "Manage your manufacturing, control your supply chain, personalize master data, \u2026"
}, {
module: 'account_accountant', name: 'Accounting and Finance',
help: "Record financial operations, automate followup, manage multi-currency, \u2026"
}
], [
{
module: 'project', name: 'Projects',
help: "Manage projects, track tasks, invoice task works, follow issues, \u2026"
}, {
module: 'hr', name: 'Human Resources',
help: "Manage employees and their contracts, follow laves, recruit people, \u2026"
}, {
module: 'marketing', name: 'Marketing',
help: "Manage campaigns, follow activities, automate emails, \u2026"
}, {
module: 'knowledge', name: 'Knowledge',
help: "Track your documents, browse your files, \u2026"
}
]
]
};
openerp.web_dashboard.ApplicationTiles = openerp.web.View.extend({
template: 'ApplicationTiles',
start: function () {
this._super();
var self = this;
return new openerp.web.DataSetSearch(
this, 'ir.ui.menu', null, [['parent_id', '=', false]])
.read_slice( ['name', 'web_icon_data', 'web_icon_hover_data'], {}, function (applications) {
// Create a matrix of 3*x applications
var rows = [];
while (applications.length) {
rows.push(applications.splice(0, 3));
this._super();
// Check for installed application
var Installer = new openerp.web.DataSet(this, 'base.setup.installer');
Installer.call('default_get', [], function (installed_modules) {
var installed = _(installed_modules).any(function (active, name) {
return _.startsWith(name, 'cat') && active; });
if(installed) {
self.do_display_root_menu();
} else {
self.do_display_installer();
}
});
},
do_display_root_menu: function() {
var self = this;
var dss = new openerp.web.DataSetSearch( this, 'ir.ui.menu', null, [['parent_id', '=', false]]);
var r = dss.read_slice( ['name', 'web_icon_data', 'web_icon_hover_data'], {}, function (applications) {
// Create a matrix of 3*x applications
var rows = [];
while (applications.length) {
rows.push(applications.splice(0, 3));
}
var tiles = QWeb.render( 'ApplicationTiles.content', {rows: rows});
self.$element.append(tiles)
.find('.oe-dashboard-home-tile')
.click(function () {
openerp.webclient.menu.on_menu_click(null, $(this).data('menuid'))
});
});
return r;
},
do_display_installer: function() {
var self = this;
var render_ctx = {
url: window.location.protocol + '//' + window.location.host + window.location.pathname,
session: self.session,
rows: openerp.web_dashboard.apps.applications
};
var installer = QWeb.render('StaticHome', render_ctx);
self.$element.append(installer);
this.$element.delegate('.oe-static-home-tile-text button', 'click', function () {
self.install_module($(this).val());
});
},
install_module: function (module_name) {
var self = this;
var Modules = new openerp.web.DataSetSearch(
this, 'ir.module.module', null,
[['name', '=', module_name], ['state', '=', 'uninstalled']]);
var Upgrade = new openerp.web.DataSet(this, 'base.module.upgrade');
$.blockUI({message:'<img src="/web/static/src/img/throbber2.gif">'});
Modules.read_slice(['id'], {}, function (records) {
if (!(records.length === 1)) { $.unblockUI(); return; }
Modules.call('state_update',
[_.pluck(records, 'id'), 'to install', ['uninstalled']],
function () {
Upgrade.call('upgrade_module', [[]], function () {
self.run_configuration_wizards();
});
}
self.$element
.append(QWeb.render(
'ApplicationTiles.content', {rows: rows}))
.find('.oe-dashboard-home-tile')
.click(function () {
var $this = $(this);
$this.closest('.openerp')
.find('.menu a[data-menu=' + $this.data('menuid') + ']')
.click();});
)
});
},
run_configuration_wizards: function () {
var self = this;
new openerp.web.DataSet(this, 'res.config').call('start', [[]], function (action) {
$.unblockUI();
self.widget_parent.widget_parent.do_action(action, function () {
openerp.webclient.do_reload();
});
});
}
});
openerp.web.client_actions.add(
'board.home.widgets', 'openerp.web_dashboard.Widget');
/*
* Widgets
* This client action designed to be used as a dashboard widget display
* the html content of a res_widget given as argument
*/
openerp.web.client_actions.add( 'board.home.widgets', 'openerp.web_dashboard.Widget');
openerp.web_dashboard.Widget = openerp.web.View.extend(/** @lends openerp.web_dashboard.Widgets# */{
template: 'HomeWidget',
/**
@ -410,4 +531,5 @@ openerp.web_dashboard.Widget = openerp.web.View.extend(/** @lends openerp.web_da
}));
}
});
};

View File

@ -30,8 +30,10 @@
</t>
<t t-name="DashBoard.action">
<div t-att-data-id="action.attrs.name" class="oe-dashboard-action">
<h2 class="oe-dashboard-action-header oe_view_title">
<h2 t-attf-class="oe-dashboard-action-header oe_view_title #{action.attrs.string ? '' : 'oe-dashboard-action-header-empty'}">
<input class="oe-dashboard-action-input" type="text" name="title" value="" style="display: none"/>
<t t-esc="action.attrs.string"/>
<t t-if="!action.attrs.string">&amp;nbsp;</t>
<span class='ui-icon ui-icon-closethick'></span>
<span class='ui-icon ui-icon-minusthick oe-dashboard-fold' t-if="!action.attrs.fold"></span>
<span class='ui-icon ui-icon-plusthick oe-dashboard-fold' t-if="action.attrs.fold"></span>
@ -110,4 +112,36 @@
<h3><t t-esc="widget.title"/></h3>
<iframe width="100%" frameborder="0" t-att-src="url"/>
</t>
<div t-name="StaticHome" class="oe-static-home">
<h1>Welcome to your new OpenERP instance.</h1>
<div class="oe-static-home-banner">
<li>Remember to bookmark this page.</li>
<li>Remember your login: <i><t t-esc="session.login"/></i></li>
<li>Choose the first OpenERP Application you want to install..</li>
</div>
<div class="oe-static-home-tiles">
<table width="100%">
<tr t-foreach="rows" t-as="row">
<td t-foreach="row" t-as="application" width="25%">
<table class="oe-static-home-tile">
<tr>
<td>
<div class="oe-static-home-tile-logo">
<img t-att-src="'/web_dashboard/static/src/img/installer_' + application.module + '.png'"/>
</div>
</td>
<td>
<div class="oe-static-home-tile-text">
<h2><t t-esc="application.name"/></h2>
<p><t t-esc="application.help"/></p>
<button type="button" t-att-value="application.module"> Install</button>
</div>
</td>
</tr>
</table>
</td>
</tr>
</table>
</div>
</div>
</template>

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