diff --git a/.bzrignore b/.bzrignore index 7ae985ce4df..b83a43bf1d4 100644 --- a/.bzrignore +++ b/.bzrignore @@ -9,4 +9,3 @@ RE:^include/ RE:^share/ RE:^man/ RE:^lib/ -logging.cfg diff --git a/addons/web/__init__.py b/addons/web/__init__.py index 2478edb81b7..06e7fa1f0e3 100644 --- a/addons/web/__init__.py +++ b/addons/web/__init__.py @@ -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 - diff --git a/addons/web/__openerp__.py b/addons/web/__openerp__.py index 74633fa4969..0afd43190d6 100644 --- a/addons/web/__openerp__.py +++ b/addons/web/__openerp__.py @@ -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', } diff --git a/addons/web/common/__init__.py b/addons/web/common/__init__.py index 9257f51d037..53bf3e3ed08 100644 --- a/addons/web/common/__init__.py +++ b/addons/web/common/__init__.py @@ -1,2 +1,6 @@ #!/usr/bin/python -from dispatch import * +import http +import nonliterals +import release +import session +import xml2json diff --git a/addons/web/common/ast.py b/addons/web/common/ast.py deleted file mode 100644 index 2fd565aa30d..00000000000 --- a/addons/web/common/ast.py +++ /dev/null @@ -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='', 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) diff --git a/addons/web/common/dates.py b/addons/web/common/dates.py deleted file mode 100644 index caa7f83c84a..00000000000 --- a/addons/web/common/dates.py +++ /dev/null @@ -1,88 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-2009 Tiny SPRL (). -# Copyright (C) 2010 OpenERP s.a. (). -# -# 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 . -# -############################################################################## - -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) diff --git a/addons/web/common/dispatch.py b/addons/web/common/dispatch.py deleted file mode 100644 index 98b948704fa..00000000000 --- a/addons/web/common/dispatch.py +++ /dev/null @@ -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 diff --git a/addons/web/common/http.py b/addons/web/common/http.py index 0186fd985cc..e23a0431a7c 100644 --- a/addons/web/common/http.py +++ b/addons/web/common/http.py @@ -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 + +# diff --git a/addons/web/common/nonliterals.py b/addons/web/common/nonliterals.py index 937da06ad9e..f6e81894a4c 100644 --- a/addons/web/common/nonliterals.py +++ b/addons/web/common/nonliterals.py @@ -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)): diff --git a/addons/web/common/openerplib/main.py b/addons/web/common/openerplib/main.py index 21f8d48ff63..5cae9ce4636 100644 --- a/addons/web/common/openerplib/main.py +++ b/addons/web/common/openerplib/main.py @@ -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. diff --git a/addons/web/common/session.py b/addons/web/common/session.py index d1997a3f903..e8027db8ea4 100644 --- a/addons/web/common/session.py +++ b/addons/web/common/session.py @@ -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 diff --git a/addons/web/common/xml2json.py b/addons/web/common/xml2json.py new file mode 100644 index 00000000000..16022624fe7 --- /dev/null +++ b/addons/web/common/xml2json.py @@ -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 diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py index 96db9c6fc3c..8120141b4f6 100644 --- a/addons/web/controllers/main.py +++ b/addons/web/controllers/main.py @@ -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(""" +html_template = """ OpenERP %(css)s - %(javascript)s + %(js)s -""") +""" + 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([''%i for i in jslist]) + js = "\n ".join(''%i for i in self.manifest_list(req, None, 'js')) + css = "\n ".join(''%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([''%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 '' % ( + 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 '' % ( + jsonp, simplejson.dumps( + {'records': data[:10]}, encoding=csvcode)) + except UnicodeDecodeError: + return '' % ( + 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 '' % ( + 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 '' % ( + 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 '' % ( + jsonp, simplejson.dumps({'error':error})) + + if code != -1: + return '' % ( + jsonp, simplejson.dumps({'success':True})) + + msg = u"Error during import: %s\n\nTrying to import record %r" % ( + message, record) + return '' % ( + jsonp, simplejson.dumps({'error': {'message':msg}})) diff --git a/addons/web/po/da.po b/addons/web/po/da.po new file mode 100644 index 00000000000..cefd844d49a --- /dev/null +++ b/addons/web/po/da.po @@ -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 , 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: openerp-web\n" +"Report-Msgid-Bugs-To: FULL NAME \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 \n" +"Language-Team: Danish \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 "   Search More..." +msgstr "   Søg efter mere...." + +#: addons/web/static/src/js/view_form.js:1672 +#, python-format +msgid "   Create \"%s\"" +msgstr "   Create \"%s\"" + +#: addons/web/static/src/js/view_form.js:1678 +msgid "   Create and Edit..." +msgstr "   Opret og rediger..." + +#: 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 "«" +msgstr "«" + +#: addons/web/static/src/xml/base.xml:0 +msgid "»" +msgstr "»" + +#: 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 " " +msgstr " " + +#: 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." diff --git a/addons/web/po/de.po b/addons/web/po/de.po new file mode 100644 index 00000000000..027f34f9866 --- /dev/null +++ b/addons/web/po/de.po @@ -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 , 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: openerp-web\n" +"Report-Msgid-Bugs-To: FULL NAME \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 \n" +"Language-Team: German \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 "   Search More..." +msgstr "   Suche mehr..." + +#: addons/web/static/src/js/view_form.js:1672 +#, python-format +msgid "   Create \"%s\"" +msgstr "   Anlegen \"%s\"" + +#: addons/web/static/src/js/view_form.js:1678 +msgid "   Create and Edit..." +msgstr "   Anlegen und Bearbeiten..." + +#: 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 "«" +msgstr "«" + +#: addons/web/static/src/xml/base.xml:0 +msgid "»" +msgstr "»" + +#: 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 " " +msgstr " " + +#: 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." diff --git a/addons/web/po/es.po b/addons/web/po/es.po new file mode 100644 index 00000000000..508b4e62245 --- /dev/null +++ b/addons/web/po/es.po @@ -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 , 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: openerp-web\n" +"Report-Msgid-Bugs-To: FULL NAME \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 \n" +"Language-Team: Spanish \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 "   Search More..." +msgstr "   Buscar más..." + +#: addons/web/static/src/js/view_form.js:1672 +#, python-format +msgid "   Create \"%s\"" +msgstr "   Crear \"%s\"" + +#: addons/web/static/src/js/view_form.js:1678 +msgid "   Create and Edit..." +msgstr "   Crear y Editar..." + +#: 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 "«" +msgstr "«" + +#: addons/web/static/src/xml/base.xml:0 +msgid "»" +msgstr "»" + +#: 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 " " +msgstr " " + +#: 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." diff --git a/addons/web/po/es_EC.po b/addons/web/po/es_EC.po new file mode 100644 index 00000000000..eb2283f6fe5 --- /dev/null +++ b/addons/web/po/es_EC.po @@ -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 , 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: openerp-web\n" +"Report-Msgid-Bugs-To: FULL NAME \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) \n" +"Language-Team: Spanish (Ecuador) \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 "   Search More..." +msgstr "   Buscar Más..." + +#: addons/web/static/src/js/view_form.js:1672 +#, python-format +msgid "   Create \"%s\"" +msgstr "   Crear \"%s\"" + +#: addons/web/static/src/js/view_form.js:1678 +msgid "   Create and Edit..." +msgstr "   Crear y Editar..." + +#: 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 "«" +msgstr "«" + +#: addons/web/static/src/xml/base.xml:0 +msgid "»" +msgstr "»" + +#: 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 " " +msgstr " " + +#: 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." diff --git a/addons/web/po/et.po b/addons/web/po/et.po new file mode 100644 index 00000000000..75269bf5cda --- /dev/null +++ b/addons/web/po/et.po @@ -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 , 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: openerp-web\n" +"Report-Msgid-Bugs-To: FULL NAME \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 \n" +"Language-Team: Estonian \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 "   Search More..." +msgstr "" + +#: addons/web/static/src/js/view_form.js:1672 +#, python-format +msgid "   Create \"%s\"" +msgstr "" + +#: addons/web/static/src/js/view_form.js:1678 +msgid "   Create and Edit..." +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 "«" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "»" +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 " " +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 "" diff --git a/addons/web/po/fr.po b/addons/web/po/fr.po new file mode 100644 index 00000000000..a4287a31030 --- /dev/null +++ b/addons/web/po/fr.po @@ -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 , 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: openerp-web\n" +"Report-Msgid-Bugs-To: FULL NAME \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) \n" +"Language-Team: French \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 "   Search More..." +msgstr "" + +#: addons/web/static/src/js/view_form.js:1672 +#, python-format +msgid "   Create \"%s\"" +msgstr "" + +#: addons/web/static/src/js/view_form.js:1678 +msgid "   Create and Edit..." +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 "«" +msgstr "«" + +#: addons/web/static/src/xml/base.xml:0 +msgid "»" +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 "" + +#: 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 " " +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 "" diff --git a/addons/web/po/gl.po b/addons/web/po/gl.po new file mode 100644 index 00000000000..b43664b9bee --- /dev/null +++ b/addons/web/po/gl.po @@ -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 , 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: openerp-web\n" +"Report-Msgid-Bugs-To: FULL NAME \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 \n" +"Language-Team: Galician \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 "   Search More..." +msgstr "   Buscar máis..." + +#: addons/web/static/src/js/view_form.js:1672 +#, python-format +msgid "   Create \"%s\"" +msgstr "   Crear \"%s\"" + +#: addons/web/static/src/js/view_form.js:1678 +msgid "   Create and Edit..." +msgstr "   Crear e Editar..." + +#: 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 "«" +msgstr "«" + +#: addons/web/static/src/xml/base.xml:0 +msgid "»" +msgstr "»" + +#: 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 " " +msgstr " " + +#: 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." diff --git a/addons/web/po/it.po b/addons/web/po/it.po new file mode 100644 index 00000000000..fc53244533b --- /dev/null +++ b/addons/web/po/it.po @@ -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 , 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: openerp-web\n" +"Report-Msgid-Bugs-To: FULL NAME \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 \n" +"Language-Team: Italian \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 "   Search More..." +msgstr "   Cerca ancora..." + +#: addons/web/static/src/js/view_form.js:1672 +#, python-format +msgid "   Create \"%s\"" +msgstr "   Crea \"%s\"" + +#: addons/web/static/src/js/view_form.js:1678 +msgid "   Create and Edit..." +msgstr "   Crea e modifica..." + +#: 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 "«" +msgstr "" + +#: addons/web/static/src/xml/base.xml:0 +msgid "»" +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 " " +msgstr " " + +#: 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." diff --git a/addons/web/po/nl_BE.po b/addons/web/po/nl_BE.po new file mode 100644 index 00000000000..2a2dccb1712 --- /dev/null +++ b/addons/web/po/nl_BE.po @@ -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 , 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: openerp-web\n" +"Report-Msgid-Bugs-To: FULL NAME \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 \n" +"Language-Team: Dutch (Belgium) \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 "   Search More..." +msgstr "   Uitgebreid zoeken..." + +#: addons/web/static/src/js/view_form.js:1672 +#, python-format +msgid "   Create \"%s\"" +msgstr "   Creër \"%s\"" + +#: addons/web/static/src/js/view_form.js:1678 +msgid "   Create and Edit..." +msgstr "   Creër en bewerk..." + +#: 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 "«" +msgstr "«" + +#: addons/web/static/src/xml/base.xml:0 +msgid "»" +msgstr "»" + +#: 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 " " +msgstr " " + +#: 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." diff --git a/addons/web/po/sl.po b/addons/web/po/sl.po new file mode 100644 index 00000000000..bc63e7ff313 --- /dev/null +++ b/addons/web/po/sl.po @@ -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 , 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: openerp-web\n" +"Report-Msgid-Bugs-To: FULL NAME \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) \n" +"Language-Team: Slovenian \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 "   Search More..." +msgstr "   Iskanje več..." + +#: addons/web/static/src/js/view_form.js:1672 +#, python-format +msgid "   Create \"%s\"" +msgstr "   Ustvari \"%s\"" + +#: addons/web/static/src/js/view_form.js:1678 +msgid "   Create and Edit..." +msgstr "   Ustvari in uredi..." + +#: 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 "«" +msgstr "«" + +#: addons/web/static/src/xml/base.xml:0 +msgid "»" +msgstr "»" + +#: 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 " " +msgstr " " + +#: 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." diff --git a/addons/web/po/web.pot b/addons/web/po/web.pot index 8d302a41fd7..adfa15066fd 100644 --- a/addons/web/po/web.pot +++ b/addons/web/po/web.pot @@ -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 \n" "Language-Team: LANGUAGE \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 "   Search More..." msgstr "" -#: addons/web/static/src/js/form.js:1486 +#: addons/web/static/src/js/view_form.js:1672 #, python-format msgid "   Create \"%s\"" msgstr "" -#: addons/web/static/src/js/form.js:1492 +#: addons/web/static/src/js/view_form.js:1678 msgid "   Create and Edit..." 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 "«" msgstr "" #: addons/web/static/src/xml/base.xml:0 -msgid "<" +msgid "»" 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 "" +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 "" diff --git a/addons/web/static/lib/jquery.deferred-queue/LICENSE b/addons/web/static/lib/jquery.deferred-queue/LICENSE new file mode 100644 index 00000000000..ee8cf44578c --- /dev/null +++ b/addons/web/static/lib/jquery.deferred-queue/LICENSE @@ -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 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. diff --git a/addons/web/static/lib/jquery.deferred-queue/README b/addons/web/static/lib/jquery.deferred-queue/README new file mode 100644 index 00000000000..71d980199c9 --- /dev/null +++ b/addons/web/static/lib/jquery.deferred-queue/README @@ -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 diff --git a/addons/web/static/lib/jquery.deferred-queue/jquery.deferred-queue.js b/addons/web/static/lib/jquery.deferred-queue/jquery.deferred-queue.js new file mode 100644 index 00000000000..7ef83342f77 --- /dev/null +++ b/addons/web/static/lib/jquery.deferred-queue/jquery.deferred-queue.js @@ -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) diff --git a/addons/web/static/lib/py.parse/.hg_archival.txt b/addons/web/static/lib/py.parse/.hg_archival.txt new file mode 100644 index 00000000000..43d5d80a9e4 --- /dev/null +++ b/addons/web/static/lib/py.parse/.hg_archival.txt @@ -0,0 +1,5 @@ +repo: 076b192d0d8ab2b92d1dbcfa3da055382f30eaea +node: 87fb1b67d6a13f10a1a328104ee4d4b2c36801ec +branch: default +latesttag: 0.2 +latesttagdistance: 1 diff --git a/addons/web/static/lib/py.parse/README b/addons/web/static/lib/py.parse/README new file mode 100644 index 00000000000..453f001ee15 --- /dev/null +++ b/addons/web/static/lib/py.parse/README @@ -0,0 +1 @@ +Parser and evaluator of Python expressions diff --git a/addons/web/static/lib/py.parse/TODO.rst b/addons/web/static/lib/py.parse/TODO.rst new file mode 100644 index 00000000000..3638b681ddc --- /dev/null +++ b/addons/web/static/lib/py.parse/TODO.rst @@ -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`_ + for *all* supported operations, optimizations can come later +* Automatically type-wrap everything (for now anyway) diff --git a/addons/web/static/lib/py.parse/lib/py.js b/addons/web/static/lib/py.parse/lib/py.js new file mode 100644 index 00000000000..0f2415f1252 --- /dev/null +++ b/addons/web/static/lib/py.parse/lib/py.js @@ -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 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> 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': 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= 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'}));; diff --git a/addons/web/static/lib/qweb/qweb2.js b/addons/web/static/lib/qweb/qweb2.js index 621ea39c74f..34457ade4fd 100644 --- a/addons/web/static/lib/qweb/qweb2.js +++ b/addons/web/static/lib/qweb/qweb2.js @@ -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) { diff --git a/addons/web/static/lib/underscore/underscore.string.js b/addons/web/static/lib/underscore/underscore.string.js index 4da2b26ec1c..d15c1f1f7ce 100644 --- a/addons/web/static/lib/underscore/underscore.string.js +++ b/addons/web/static/lib/underscore/underscore.string.js @@ -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 + // 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,'&').replace(//g,'>') - .replace(/"/g, '"').replace(/'/g, "'"); - }, - - unescapeHTML: function(str) { - return String(str||'').replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>') - .replace(/"/g, '"').replace(/'/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 - * 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,'&').replace(//g,'>') + .replace(/"/g, '"').replace(/'/g, "'"); + }), + + unescapeHTML: sArgs(function(str) { + return str.replace(/</g, '<').replace(/>/g, '>') + .replace(/"/g, '"').replace(/'/g, "'").replace(/&/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)); diff --git a/addons/web/static/src/css/base.css b/addons/web/static/src/css/base.css index c75fe786543..744d218a83b 100644 --- a/addons/web/static/src/css/base.css +++ b/addons/web/static/src/css/base.css @@ -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; } diff --git a/addons/web/static/src/css/data_import.css b/addons/web/static/src/css/data_import.css new file mode 100644 index 00000000000..1fb3b22aa45 --- /dev/null +++ b/addons/web/static/src/css/data_import.css @@ -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; +} diff --git a/addons/web/static/src/img/box-a-header-a.gif b/addons/web/static/src/img/box-a-header-a.gif new file mode 100644 index 00000000000..6b461b42bfe Binary files /dev/null and b/addons/web/static/src/img/box-a-header-a.gif differ diff --git a/addons/web/static/src/img/gradientlinebg.gif b/addons/web/static/src/img/gradientlinebg.gif new file mode 100644 index 00000000000..f40bd9c0f6a Binary files /dev/null and b/addons/web/static/src/img/gradientlinebg.gif differ diff --git a/addons/web/static/src/js/boot.js b/addons/web/static/src/js/boot.js index b9d5180b5c4..f41185be0c6 100644 --- a/addons/web/static/src/js/boot.js +++ b/addons/web/static/src/js/boot.js @@ -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' + QWeb.render('DialogWarning', {error: error}) + '').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:''}); @@ -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() { - } + }, + }); }; diff --git a/addons/web/static/src/js/core.js b/addons/web/static/src/js/core.js index 2e9294ded12..39a1ba7ef64 100644 --- a/addons/web/static/src/js/core.js +++ b/addons/web/static/src/js/core.js @@ -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', { - '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; +} }; diff --git a/addons/web/static/src/js/data.js b/addons/web/static/src/js/data.js index e5d323c8a96..069506586ad 100644 --- a/addons/web/static/src/js/data.js +++ b/addons/web/static/src/js/data.js @@ -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(); diff --git a/addons/web/static/src/js/data_import.js b/addons/web/static/src/js/data_import.js new file mode 100644 index 00000000000..711e790dfaa --- /dev/null +++ b/addons/web/static/src/js/data_import.js @@ -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>} 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 = $('
Destination fields should only be selected once, some fields are selected more than once:
').insertBefore(this.$element.find('#result')); + var $dupes = $('
').appendTo($err); + _(duplicates).each(function(elements, value) { + $('
').text(value).appendTo($dupes); + _(elements).each(function(element) { + var cell = $(element).closest('td'); + $('
').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('
*Required Fields are not selected : ' + missing_fields + '.
'); + return false; + } + return true; + }, + stop: function() { + $(this.$dialog).remove(); + this._super(); + } +}); +}; diff --git a/addons/web/static/src/js/formats.js b/addons/web/static/src/js/formats.js index e7feedf26a5..3ab972f7a86 100644 --- a/addons/web/static/src/js/formats.js +++ b/addons/web/static/src/js/formats.js @@ -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 [ diff --git a/addons/web/static/src/js/search.js b/addons/web/static/src/js/search.js index db91d6bfd27..c7aa1e3cfe3 100644 --- a/addons/web/static/src/js/search.js +++ b/addons/web/static/src/js/search.js @@ -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 + + + + + + + + + + + +
@@ -253,33 +271,18 @@ - - - - - - + + t-att-value="widget.selected_login || ''" autofocus="true"/> + t-att-value="widget.selected_password || ''"/> @@ -330,6 +333,7 @@
+
@@ -445,11 +449,11 @@ -

- - + +

+

@@ -465,17 +469,20 @@

-

-
    +

    +
+
+ + +
  • - -
    +
    • Fields
    • @@ -537,7 +544,7 @@ @@ -561,21 +568,7 @@ Delete - - - - - - - - - - + @@ -605,8 +598,26 @@ + + + + + + + + + + + + + @@ -614,7 +625,8 @@ + t-att-data-id="record.get('id')" + t-att-style="view.color_for(record)"> @@ -628,7 +640,7 @@ - + @@ -639,19 +651,15 @@ -
      +
      - - - +
      @@ -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}" > @@ -722,8 +729,8 @@
        -
      • - +
      • +
      • @@ -733,17 +740,23 @@ -
        +
        + + +

        + + +
        -