diff --git a/connector/README.rst b/connector/README.rst new file mode 100644 index 000000000..2280dbd19 --- /dev/null +++ b/connector/README.rst @@ -0,0 +1,166 @@ +========= +Connector +========= + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:c3fb5d7af399741b082a3725c3698dd038043c4a6a855da345ea1f9f9cb3a979 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png + :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html + :alt: License: LGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fconnector-lightgray.png?logo=github + :target: https://github.com/OCA/connector/tree/18.0/connector + :alt: OCA/connector +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/connector-18-0/connector-18-0-connector + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/connector&target_branch=18.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This is a framework designed to build connectors with external systems, +usually called ``Backends`` in the documentation. + +Documentation: http://odoo-connector.com + +It features: + +- A jobs queue + + In which the connectors can push functions (synchronization tasks) + to be executed later. + +- An event pattern + + The connectors can subscribe listener functions on the events, + executed when the events are fired. + +- Connector base classes + + Called ``ConnectorUnit``. + + Include base classes for the use in connectors, ready to be + extended: + + - ``Synchronizer``: flow of an import or export + - ``Mapper``: transform a record according to mapping rules + - ``Binder``: link external IDs with local IDS + - ``BackendAdapter``: adapter interface for the exchanges with + the backend + - But ``ConnectorUnit`` can be extended to accomplish any task + +- A multi-backend support + + Each ``ConnectorUnit`` can be registered amongst a backend type + (eg. Magento) and a backend version (allow to have a different + ``Mapper`` for each backend's version for instance) + +It is used for example used to connect +`Magento `__ and +`Prestashop `__, but also +used with Solr, CMIS, ... + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +This module does nothing on its own. It is a ground for developing +advanced connector modules. For further information, please go on: +http://odoo-connector.com + +Changelog +========= + +Next +---- + +12.0.1.0.0 (2018-11-26) +----------------------- + +- [MIGRATION] from 12.0 branched at rev. 324e006 + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* Camptocamp + +Contributors +------------ + +- Guewen Baconnier at Camptocamp +- Alexandre Fayolle at Camptocamp +- Benoit Guillot at Akretion +- Nicolas Bessi at Camptocamp +- Joël Grand-Guillaume at Camptocamp +- Arthur Vuillard at Akretion +- Sebastien Beau at Akretion +- Laurent Mignon at Acsone +- Leonardo Pistone at Camptocamp +- David Béal at Akretion +- Christophe Combelles at Anybox +- Stéphane Bidoul at Acsone +- Malte Jacobi at IBO / HTW +- Laetitia Gangloff at Acsone +- David Lefever at Taktik S.A. +- Jos de Graeve at Apertoso NV +- Jean-Sébastien Suzanne at Anybox +- Leonardo Donelli at MONK Software +- Mathias Colpaert +- Yannick Vaucher at Camptocamp +- Nicolas Piganeau at NDP Systèmes +- Florent Thomas at Mind And Go +- Matthieu Dietrich at Camptocamp +- Olivier Laurent at Acsone +- Eric Antones at NuoBiT Solutions S.L. +- Asier Neira at Factor Libre S.L. +- Nguyen Minh Chien at Trobz. + +Other credits +------------- + +The migration of this module from 17.0 to 18.0 was financially supported +by Camptocamp. + +Maintainers +----------- + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/connector `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/connector/__init__.py b/connector/__init__.py new file mode 100644 index 000000000..f24d3e242 --- /dev/null +++ b/connector/__init__.py @@ -0,0 +1,2 @@ +from . import components +from . import models diff --git a/connector/__manifest__.py b/connector/__manifest__.py new file mode 100644 index 000000000..ac43e3e46 --- /dev/null +++ b/connector/__manifest__.py @@ -0,0 +1,18 @@ +# Copyright 2013 Camptocamp SA +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html) + +{ + "name": "Connector", + "version": "18.0.1.0.0", + "author": "Camptocamp,Odoo Community Association (OCA)", + "website": "https://github.com/OCA/connector", + "license": "LGPL-3", + "category": "Generic Modules", + "depends": ["mail", "queue_job", "component", "component_event"], + "data": [ + "security/connector_security.xml", + "views/connector_menu.xml", + "views/res_partner_views.xml", + ], + "installable": True, +} diff --git a/connector/components/__init__.py b/connector/components/__init__.py new file mode 100644 index 000000000..500880625 --- /dev/null +++ b/connector/components/__init__.py @@ -0,0 +1,7 @@ +from . import core +from . import backend_adapter +from . import binder +from . import mapper +from . import listener +from . import locker +from . import synchronizer diff --git a/connector/components/backend_adapter.py b/connector/components/backend_adapter.py new file mode 100644 index 000000000..41e2246c0 --- /dev/null +++ b/connector/components/backend_adapter.py @@ -0,0 +1,64 @@ +# Copyright 2013 Camptocamp SA +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html) + +""" + +Backend Adapter +=============== + +An external adapter has a common interface to speak with the backend. +It translates the basic orders (search, read, write) to the protocol +used by the backend. + +""" + +from odoo.addons.component.core import AbstractComponent + + +class BackendAdapter(AbstractComponent): + """Base Backend Adapter for the connectors""" + + _name = "base.backend.adapter" + _inherit = "base.connector" + _usage = "backend.adapter" + + +# pylint: disable=W8106 +class CRUDAdapter(AbstractComponent): + """Base External Adapter specialized in the handling + of records on external systems. + + This is an empty shell, Components can inherit and implement their own + implementation for the methods. + + """ + + _name = "base.backend.adapter.crud" + _inherit = "base.backend.adapter" + _usage = "backend.adapter" + + def search(self, *args, **kwargs): + """Search records according to some criterias + and returns a list of ids""" + raise NotImplementedError + + def read(self, *args, **kwargs): + """Returns the information of a record""" + raise NotImplementedError + + def search_read(self, *args, **kwargs): + """Search records according to some criterias + and returns their information""" + raise NotImplementedError + + def create(self, *args, **kwargs): + """Create a record on the external system""" + raise NotImplementedError + + def write(self, *args, **kwargs): + """Update records on the external system""" + raise NotImplementedError + + def delete(self, *args, **kwargs): + """Delete a record on the external system""" + raise NotImplementedError diff --git a/connector/components/binder.py b/connector/components/binder.py new file mode 100644 index 000000000..9987cf7ed --- /dev/null +++ b/connector/components/binder.py @@ -0,0 +1,147 @@ +# Copyright 2013 Camptocamp SA +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html) + +""" +Binders +======= + +Binders are components that know how to find the external ID for an +Odoo ID, how to find the Odoo ID for an external ID and how to +create the binding between them. + +""" + +from odoo import fields, models + +from odoo.addons.component.core import AbstractComponent + + +class Binder(AbstractComponent): + """For one record of a model, capable to find an external or + internal id, or create the binding (link) between them + + This is a default implementation that can be inherited or reimplemented + in the connectors. + + This implementation assumes that binding models are ``_inherits`` of + the models they are binding. + + """ + + _name = "base.binder" + _inherit = "base.connector" + _usage = "binder" + + _external_field = "external_id" # override in sub-classes + _backend_field = "backend_id" # override in sub-classes + _odoo_field = "odoo_id" # override in sub-classes + _sync_date_field = "sync_date" # override in sub-classes + + def to_internal(self, external_id, unwrap=False): + """Give the Odoo recordset for an external ID + + :param external_id: external ID for which we want + the Odoo ID + :param unwrap: if True, returns the normal record + else return the binding record + :return: a recordset, depending on the value of unwrap, + or an empty recordset if the external_id is not mapped + :rtype: recordset + """ + context = self.env.context + bindings = self.model.with_context(active_test=False).search( + [ + (self._external_field, "=", external_id), + (self._backend_field, "=", self.backend_record.id), + ] + ) + if not bindings: + if unwrap: + return self.model.browse()[self._odoo_field] + return self.model.browse() + bindings.ensure_one() + if unwrap: + bindings = bindings[self._odoo_field] + bindings = bindings.with_context(**context) + return bindings + + def to_external(self, binding, wrap=False): + """Give the external ID for an Odoo binding ID + + :param binding: Odoo binding for which we want the external id + :param wrap: if True, binding is a normal record, the + method will search the corresponding binding and return + the external id of the binding + :return: external ID of the record + """ + if isinstance(binding, models.BaseModel): + binding.ensure_one() + else: + binding = self.model.browse(binding) + if wrap: + binding = self.model.with_context(active_test=False).search( + [ + (self._odoo_field, "=", binding.id), + (self._backend_field, "=", self.backend_record.id), + ] + ) + if not binding: + return None + binding.ensure_one() + return binding[self._external_field] + return binding[self._external_field] + + def bind(self, external_id, binding): + """Create the link between an external ID and an Odoo ID + + :param external_id: external id to bind + :param binding: Odoo record to bind + :type binding: int + """ + # Prevent False, None, or "", but not 0 + assert (external_id or external_id == 0) and binding, ( + "external_id or binding missing, " f"got: {external_id}, {binding}" + ) + # avoid to trigger the export when we modify the `external_id` + now_fmt = fields.Datetime.now() + if isinstance(binding, models.BaseModel): + binding.ensure_one() + else: + binding = self.model.browse(binding) + binding.with_context(connector_no_export=True).write( + { + self._external_field: external_id, + self._sync_date_field: now_fmt, + } + ) + + def unwrap_binding(self, binding): + """For a binding record, gives the normal record. + + Example: when called with a ``magento.product.product`` id, + it will return the corresponding ``product.product`` id. + + :param browse: when True, returns a browse_record instance + rather than an ID + """ + if isinstance(binding, models.BaseModel): + binding.ensure_one() + else: + binding = self.model.browse(binding) + + return binding[self._odoo_field] + + def unwrap_model(self): + """For a binding model, gives the normal model. + + Example: when called on a binder for ``magento.product.product``, + it will return ``product.product``. + """ + try: + column = self.model._fields[self._odoo_field] + except KeyError as err: + raise ValueError( + f"Cannot unwrap model {self.model._name}, because it has no " + f"{self._odoo_field} fields" + ) from err + return column.comodel_name diff --git a/connector/components/core.py b/connector/components/core.py new file mode 100644 index 000000000..57e14bcb0 --- /dev/null +++ b/connector/components/core.py @@ -0,0 +1,136 @@ +# Copyright 2017 Camptocamp SA +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html) + +""" + +Base Component +============== + +The connector proposes a 'base' Component, which can be used in +the ``_inherit`` of your own components. This is not a +requirement. It is already inherited by every component +provided by the Connector. + +Components are organized according to different usages. The connector suggests +5 main kinds of Components. Each might have a few different usages. You can be +as creative as you want when it comes to creating new ones though. + +One "usage" is responsible for a specific work, and alongside with the +collection (the backend) and the model, the usage will be used to find the +needed component for a task. + +Some of the Components have an implementation in the ``Connector`` addon, but +some are empty shells that need to be implemented in the different connectors. + +The usual categories are: + +:py:class:`~connector.components.binder.Binder` + The ``binders`` give the external ID or Odoo ID from respectively an + Odoo ID or an external ID. A default implementation is available. + + Most common usages: + + * ``binder`` + +:py:class:`~connector.components.mapper.Mapper` + The ``mappers`` transform a external record into an Odoo record or + conversely. + + Most common usages: + + * ``import.mapper`` + * ``export.mapper`` + +:py:class:`~connector.components.backend_adapter.BackendAdapter` + The ``backend.adapters`` implements the discussion with the ``backend's`` + APIs. They usually adapt their APIs to a common interface (CRUD). + + Most common usages: + + * ``backend.adapter`` + +:py:class:`~connector.components.synchronizer.Synchronizer` + A ``synchronizer`` is the main piece of a synchronization. It + orchestrates the flow of a synchronization and use the other + Components + + Most common usages: + + * ``record.importer`` + * ``record.exporter`` + * ``batch.importer`` + * ``batch.exporter`` + +The possibilities for components do not stop there, look at the +:class:`~connector.components.locker.RecordLocker` for an example of +single-purpose, decoupled component. + + +""" + +from odoo.addons.component.core import AbstractComponent +from odoo.addons.queue_job.exception import RetryableJobError + +from ..database import pg_try_advisory_lock + + +class BaseConnectorComponent(AbstractComponent): + """Base component for the connector + + Is inherited by every components of the Connector (Binder, Mapper, ...) + and adds a few methods which are of common usage in the connectors. + + """ + + _name = "base.connector" + + @property + def backend_record(self): + """Backend record we are working with""" + # backward compatibility + return self.work.collection + + def binder_for(self, model=None): + """Shortcut to get Binder for a model + + Equivalent to: ``self.component(usage='binder', model_name='xxx')`` + + """ + return self.component(usage="binder", model_name=model) + + def advisory_lock_or_retry(self, lock, retry_seconds=1): + """Acquire a Postgres transactional advisory lock or retry job + + When the lock cannot be acquired, it raises a + :exc:`odoo.addons.queue_job.exception.RetryableJobError` so the job + is retried after n ``retry_seconds``. + + Usage example: + + .. code-block:: python + + lock_name = 'import_record({}, {}, {}, {})'.format( + self.backend_record._name, + self.backend_record.id, + self.model._name, + self.external_id, + ) + self.advisory_lock_or_retry(lock_name, retry_seconds=2) + + See :func:`odoo.addons.connector.connector.pg_try_advisory_lock` for + details. + + :param lock: The lock name. Can be anything convertible to a + string. It needs to represent what should not be synchronized + concurrently, usually the string will contain at least: the + action, the backend name, the backend id, the model name, the + external id + :param retry_seconds: number of seconds after which a job should + be retried when the lock cannot be acquired. + """ + if not pg_try_advisory_lock(self.env, lock): + raise RetryableJobError( + "Could not acquire advisory lock", + seconds=retry_seconds, + ignore_retry=True, + ) diff --git a/connector/components/listener.py b/connector/components/listener.py new file mode 100644 index 000000000..3637e3b61 --- /dev/null +++ b/connector/components/listener.py @@ -0,0 +1,50 @@ +# Copyright 2013 Camptocamp SA +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html) + +""" +Listeners +========= + +Listeners are Components notified when events happen. +Documentation in :mod:`odoo.addons.component_event.components.event` + +The base listener for the connectors add a method +:meth:`ConnectorListener.no_connector_export` which can be used with +:func:`odoo.addons.component_event.skip_if`. + + +""" + +from odoo.addons.component.core import AbstractComponent + + +class ConnectorListener(AbstractComponent): + """Base Backend Adapter for the connectors""" + + _name = "base.connector.listener" + _inherit = ["base.connector", "base.event.listener"] + + def no_connector_export(self, record): + """Return if the 'connector_no_export' has been set in context + + To be used with :func:`odoo.addons.component_event.skip_if` + on Events:: + + from odoo.addons.component.core import Component + from odoo.addons.component_event import skip_if + + + class MyEventListener(Component): + _name = 'my.event.listener' + _inherit = 'base.connector.event.listener' + _apply_on = ['magento.res.partner'] + + @skip_if(lambda: self, record, *args, **kwargs: + self.no_connector_export(record)) + def on_record_write(self, record, fields=None): + record.with_delay().export_record() + + """ + return record.env.context.get("no_connector_export") or record.env.context.get( + "connector_no_export" + ) diff --git a/connector/components/locker.py b/connector/components/locker.py new file mode 100644 index 000000000..cb7c09811 --- /dev/null +++ b/connector/components/locker.py @@ -0,0 +1,70 @@ +# Copyright 2018 Camptocamp SA +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html) + +import logging + +import psycopg2 + +from odoo.addons.component.core import Component + +from ..exception import RetryableJobError + +_logger = logging.getLogger(__name__) + + +class RecordLocker(Component): + """Component allowing to lock record(s) for the current transaction + + Example of usage:: + + self.component('record.locker').lock(self.records) + + See the definition of :meth:`~lock` for details. + """ + + _name = "base.record.locker" + _inherit = ["base.connector"] + _usage = "record.locker" + + def lock(self, records, seconds=None, ignore_retry=True): + """Lock the records. + + Lock the record so we are sure that only one job is running for this + record(s) if concurrent jobs have to run a job for the same record(s). + When concurrent jobs try to work on the same record(s), the first one + will lock and proceed, the others will fail to acquire it and will be + retried later + (:exc:`~odoo.addons.queue_job.exception.RetryableJobError` is raised). + + The lock is using a ``FOR UPDATE NOWAIT`` so any concurrent transaction + trying FOR UPDATE/UPDATE will be rejected until the current transaction + is committed or rollbacked. + + A classical use case for this is to prevent concurrent exports. + + The following parameters are forwarded to the exception + :exc:`~odoo.addons.queue_job.exception.RetryableJobError` + + :param seconds: In case of retry because the lock cannot be acquired, + in how many seconds it must be retried. If not set, + the queue_job configuration is used. + :param ignore_retry: If True, the retry counter of the job will not be + increased. + """ + sql = f"SELECT id FROM {self.model._table} WHERE ID IN %s FOR UPDATE NOWAIT" + try: + self.env.cr.execute(sql, (tuple(records.ids),), log_exceptions=False) + except psycopg2.OperationalError as err: + _logger.info( + "A concurrent job is already working on the same " + "record (%s with one id in %s). Job delayed later.", + self.model._name, + tuple(records.ids), + ) + raise RetryableJobError( + "A concurrent job is already working on the same record " + f"({self.model._name} with one id in {tuple(records.ids)}). The job " + f"will be retried later.", + seconds=seconds, + ignore_retry=ignore_retry, + ) from err diff --git a/connector/components/mapper.py b/connector/components/mapper.py new file mode 100644 index 000000000..ddd77d5a7 --- /dev/null +++ b/connector/components/mapper.py @@ -0,0 +1,1055 @@ +# Copyright 2017 Camptocamp SA +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html) + +""" + +Mappers +======= + +Mappers are the components responsible to transform +external records into Odoo records and conversely. + +""" + +import logging +from collections import namedtuple +from contextlib import contextmanager + +from odoo import models + +from odoo.addons.component.core import AbstractComponent +from odoo.addons.component.exception import NoComponentError + +from ..exception import MappingError + +_logger = logging.getLogger(__name__) + + +__all__ = [ + "Mapper", + "ImportMapper", + "ExportMapper", + "mapping", + "changed_by", + "only_create", + "none", + "convert", + "m2o_to_external", + "external_to_m2o", + "follow_m2o_relations", + "MapRecord", + "MapChild", + "ImportMapChild", + "ExportMapChild", +] + + +def mapping(func): + """Decorator, declare that a method is a mapping method. + + It is then used by the :py:class:`Mapper` to convert the records. + + Usage:: + + @mapping + def any(self, record): + return {'output_field': record['input_field']} + + """ + func.is_mapping = True + return func + + +def changed_by(*args): + """Decorator for the mapping methods (:py:func:`mapping`) + + When fields are modified in Odoo, we want to export only the + modified fields. Using this decorator, we can specify which fields + updates should trigger which mapping method. + + If ``changed_by`` is empty, the mapping is always active. + + As far as possible, this decorator should be used for the exports, + thus, when we do an update on only a small number of fields on a + record, the size of the output record will be limited to only the + fields really having to be exported. + + Usage:: + + @changed_by('input_field') + @mapping + def any(self, record): + return {'output_field': record['input_field']} + + :param ``*args``: field names which trigger the mapping when modified + + """ + + def register_mapping(func): + func.changed_by = args + return func + + return register_mapping + + +def only_create(func): + """Decorator for the mapping methods (:py:func:`mapping`) + + A mapping decorated with ``only_create`` means that it has to be + used only for the creation of the records. + + Usage:: + + @only_create + @mapping + def any(self, record): + return {'output_field': record['input_field']} + + """ + func.only_create = True + return func + + +def none(field): + """A modifier intended to be used on the ``direct`` mappings. + + Replace the False-ish values by None. + It can be used in a pipeline of modifiers when . + + Example:: + + direct = [(none('source'), 'target'), + (none(m2o_to_external('rel_id'), 'rel_id')] + + :param field: name of the source field in the record + :param binding: True if the relation is a binding record + """ + + def modifier(self, record, to_attr): + if callable(field): + result = field(self, record, to_attr) + else: + result = record[field] + if not result: + return None + return result + + return modifier + + +def convert(field, conv_type): + """A modifier intended to be used on the ``direct`` mappings. + + Convert a field's value to a given type. + + Example:: + + direct = [(convert('source', str), 'target')] + + :param field: name of the source field in the record + :param binding: True if the relation is a binding record + """ + + def modifier(self, record, to_attr): + value = record[field] + if not value: + return False + return conv_type(value) + + return modifier + + +def m2o_to_external(field, binding=None): + """A modifier intended to be used on the ``direct`` mappings. + + For a many2one, get the external ID and returns it. + + When the field's relation is not a binding (i.e. it does not point to + something like ``magento.*``), the binding model needs to be provided + in the ``binding`` keyword argument. + + Example:: + + direct = [(m2o_to_external('country_id', + binding='magento.res.country'), 'country'), + (m2o_to_external('magento_country_id'), 'country')] + + :param field: name of the source field in the record + :param binding: name of the binding model if the relation is not a binding + """ + + def modifier(self, record, to_attr): + if not record[field]: + return False + column = self.model._fields[field] + if column.type != "many2one": + raise ValueError( + f"The column {field} should be a Many2one, got {type(column)}" + ) + rel_id = record[field].id + if binding is None: + binding_model = column.comodel_name + else: + binding_model = binding + binder = self.binder_for(binding_model) + # if a relation is not a binding, we wrap the record in the + # binding, we'll return the id of the binding + wrap = bool(binding) + value = binder.to_external(rel_id, wrap=wrap) + if not value: + raise MappingError( + "Can not find an external id for record " + "{} in model {} {} wrapping".format( + rel_id, binding_model, "with" if wrap else "without" + ) + ) + return value + + return modifier + + +def external_to_m2o(field, binding=None): + """A modifier intended to be used on the ``direct`` mappings. + + For a field from a backend which is an ID, search the corresponding + binding in Odoo and returns it. + + When the field's relation is not a binding (i.e. it does not point to + something like ``magento.*``), the binding model needs to be provided + in the ``binding`` keyword argument. + + Example:: + + direct = [(external_to_m2o('country', binding='magento.res.country'), + 'country_id'), + (external_to_m2o('country'), 'magento_country_id')] + + :param field: name of the source field in the record + :param binding: name of the binding model if the relation is not a binding + """ + + def modifier(self, record, to_attr): + if not record[field]: + return False + column = self.model._fields[to_attr] + if column.type != "many2one": + raise ValueError( + f"The column {to_attr} should be a Many2one, got {type(column)}" + ) + rel_id = record[field] + if binding is None: + binding_model = column.comodel_name + else: + binding_model = binding + binder = self.binder_for(binding_model) + # if we want the normal record, not a binding, + # we ask to the binder to unwrap the binding + unwrap = bool(binding) + record = binder.to_internal(rel_id, unwrap=unwrap) + if not record: + raise MappingError( + "Can not find an existing {} for external " + "record {} {} unwrapping".format( + binding_model, rel_id, "with" if unwrap else "without" + ) + ) + if isinstance(record, models.BaseModel): + return record.id + else: + _logger.debug( + "Binder for %s returned an id, " + "returning a record should be preferred.", + binding_model, + ) + return record + + return modifier + + +def follow_m2o_relations(field): + """A modifier intended to be used on ``direct`` mappings. + + 'Follows' Many2one relations and return the final field value. + + Examples: + Assuming model is ``product.product``:: + + direct = [ + (follow_m2o_relations('product_tmpl_id.categ_id.name'), 'cat')] + + :param field: field "path", using dots for relations as usual in Odoo + """ + + def modifier(self, record, to_attr): + attrs = field.split(".") + value = record + for attr in attrs: + value = getattr(value, attr) + return value + + return modifier + + +MappingDefinition = namedtuple("MappingDefinition", ["changed_by", "only_create"]) + + +class MapChild(AbstractComponent): + """MapChild is responsible to convert items. + + Items are sub-records of a main record. + In this example, the items are the records in ``lines``:: + + sales = {'name': 'SO10', + 'lines': [{'product_id': 1, 'quantity': 2}, + {'product_id': 2, 'quantity': 2}]} + + A MapChild is always called from another :py:class:`Mapper` which + provides a ``children`` configuration. + + Considering the example above, the "main" :py:class:`Mapper` would + returns something as follows:: + + {'name': 'SO10', + 'lines': [(0, 0, {'product_id': 11, 'quantity': 2}), + (0, 0, {'product_id': 12, 'quantity': 2})]} + + A MapChild is responsible to: + + * Find the :py:class:`Mapper` to convert the items + * Possibly filter out some lines (can be done by inheriting + :py:meth:`skip_item`) + * Convert the items' records using the found :py:class:`Mapper` + * Format the output values to the format expected by Odoo or the + backend (as seen above with ``(0, 0, {values})`` + + A MapChild can be extended like any other + :py:class:`~component.core.Component`. + However, it is not mandatory to explicitly create a MapChild for + each children mapping, the default one will be used + (:py:class:`ImportMapChild` or :py:class:`ExportMapChild`). + + The implementation by default does not take care of the updates: if + I import a sales order 2 times, the lines will be duplicated. This + is not a problem as long as an importation should only support the + creation (typical for sales orders). It can be implemented on a + case-by-case basis by inheriting :py:meth:`get_item_values` and + :py:meth:`format_items`. + + """ + + _name = "base.map.child" + _inherit = "base.connector" + + def _child_mapper(self): + raise NotImplementedError + + def skip_item(self, map_record): + """Hook to implement in sub-classes when some child + records should be skipped. + + The parent record is accessible in ``map_record``. + If it returns True, the current child record is skipped. + + :param map_record: record that we are converting + :type map_record: :py:class:`MapRecord` + """ + return False + + def get_items(self, items, parent, to_attr, options): + """Returns the formatted output values of items from a main record + + :param items: list of item records + :type items: list + :param parent: parent record + :param to_attr: destination field (can be used for introspecting + the relation) + :type to_attr: str + :param options: dict of options, herited from the main mapper + :return: formatted output values for the item + + """ + mapper = self._child_mapper() + mapped = [] + for item in items: + map_record = mapper.map_record(item, parent=parent) + if self.skip_item(map_record): + continue + item_values = self.get_item_values(map_record, to_attr, options) + if item_values: + mapped.append(item_values) + return self.format_items(mapped) + + def get_item_values(self, map_record, to_attr, options): + """Get the raw values from the child Mappers for the items. + + It can be overridden for instance to: + + * Change options + * Use a :py:class:`~connector.connector.Binder` to know if an + item already exists to modify an existing item, rather than to + add it + + :param map_record: record that we are converting + :type map_record: :py:class:`MapRecord` + :param to_attr: destination field (can be used for introspecting + the relation) + :type to_attr: str + :param options: dict of options, herited from the main mapper + + """ + return map_record.values(**options) + + def format_items(self, items_values): + """Format the values of the items mapped from the child Mappers. + + It can be overridden for instance to add the Odoo + relationships commands ``(6, 0, [IDs])``, ... + + As instance, it can be modified to handle update of existing + items: check if an 'id' has been defined by + :py:meth:`get_item_values` then use the ``(1, ID, {values}``) + command + + :param items_values: mapped values for the items + :type items_values: list + + """ + return items_values + + +class ImportMapChild(AbstractComponent): + """:py:class:`MapChild` for the Imports""" + + _name = "base.map.child.import" + _inherit = "base.map.child" + _usage = "import.map.child" + + def _child_mapper(self): + return self.component(usage="import.mapper") + + def format_items(self, items_values): + """Format the values of the items mapped from the child Mappers. + + It can be overridden for instance to add the Odoo + relationships commands ``(6, 0, [IDs])``, ... + + As instance, it can be modified to handle update of existing + items: check if an 'id' has been defined by + :py:meth:`get_item_values` then use the ``(1, ID, {values}``) + command + + :param items_values: list of values for the items to create + :type items_values: list + + """ + return [(0, 0, values) for values in items_values] + + +class ExportMapChild(AbstractComponent): + """:py:class:`MapChild` for the Exports""" + + _name = "base.map.child.export" + _inherit = "base.map.child" + _usage = "export.map.child" + + def _child_mapper(self): + return self.component(usage="export.mapper") + + +class Mapper(AbstractComponent): + """A Mapper translates an external record to an Odoo record and + conversely. The output of a Mapper is a ``dict``. + + 3 types of mappings are supported: + + Direct Mappings + Example:: + + direct = [('source', 'target')] + + Here, the ``source`` field will be copied in the ``target`` field. + + A modifier can be used in the source item. + The modifier will be applied to the source field before being + copied in the target field. + It should be a closure function respecting this idiom:: + + def a_function(field): + ''' ``field`` is the name of the source field. + + Naming the arg: ``field`` is required for the conversion''' + def modifier(self, record, to_attr): + ''' self is the current Mapper, + record is the current record to map, + to_attr is the target field''' + return record[field] + return modifier + + And used like that:: + + direct = [ + (a_function('source'), 'target'), + ] + + A more concrete example of modifier:: + + def convert(field, conv_type): + ''' Convert the source field to a defined ``conv_type`` + (ex. str) before returning it''' + def modifier(self, record, to_attr): + value = record[field] + if not value: + return None + return conv_type(value) + return modifier + + And used like that:: + + direct = [ + (convert('myfield', float), 'target_field'), + ] + + More examples of modifiers: + + * :py:func:`convert` + * :py:func:`m2o_to_external` + * :py:func:`external_to_m2o` + + Method Mappings + A mapping method allows to execute arbitrary code and return one + or many fields:: + + @mapping + def compute_state(self, record): + # compute some state, using the ``record`` or not + state = 'pending' + return {'state': state} + + We can also specify that a mapping methods should be applied + only when an object is created, and never applied on further + updates:: + + @only_create + @mapping + def default_warehouse(self, record): + # get default warehouse + warehouse_id = ... + return {'warehouse_id': warehouse_id} + + Submappings + When a record contains sub-items, like the lines of a sales order, + we can convert the children using another Mapper:: + + children = [('items', 'line_ids', 'model.name')] + + It allows to create the sales order and all its lines with the + same call to :py:meth:`odoo.models.BaseModel.create()`. + + When using ``children`` for items of a record, we need to create + a :py:class:`Mapper` for the model of the items, and optionally a + :py:class:`MapChild`. + + Usage of a Mapper:: + + >>> mapper = self.component(usage='mapper') + >>> map_record = mapper.map_record(record) + >>> values = map_record.values() + >>> values = map_record.values(for_create=True) + >>> values = map_record.values(fields=['name', 'street']) + + """ + + _name = "base.mapper" + _inherit = "base.connector" + _usage = "mapper" + + direct = [] # direct conversion of a field to another (from_attr, to_attr) + children = [] # conversion of sub-records (from_attr, to_attr, model) + + _map_methods = None + + _map_child_usage = None + _map_child_fallback = None + + @classmethod + def _build_mapper_component(cls): + """Build a Mapper component + + When a Mapper component is built, we will look into every of its bases + and look for methods decorated by ``@mapping`` or ``@changed_by``. We + keep the definitions in a ``_map_methods`` attribute for later use by + the Mapper instances. + + The ``__bases__`` of a newly generated Component are of 2 kinds: + + * other dynamically generated components (below 'base' and + 'second.mapper') + * "real" Python classes applied on top of existing components (here + ThirdMapper) + + :: + + >>> cls.__bases__ + (, + , + ) + + This method traverses these bases, from the bottom to the top, and + merges the mapping definitions. It reuses the computed definitions + for the generated components (for which this code already ran), and + inspect the real classes to find mapping methods. + + """ + + map_methods = {} + for base in reversed(cls.__bases__): + if hasattr(base, "_map_methods"): + # this is already a dynamically generated Component, so we can + # use its existing mappings + base_map_methods = base._map_methods or {} + for attr_name, definition in base_map_methods.items(): + if attr_name in map_methods: + # Update the existing @changed_by with the content + # of each base (it is mutated in place). + mapping_changed_by = map_methods[attr_name].changed_by + mapping_changed_by.update(definition.changed_by) + # keep the last value for @only_create + if definition.only_create: + new_definition = MappingDefinition( + mapping_changed_by, definition.only_create + ) + map_methods[attr_name] = new_definition + else: + map_methods[attr_name] = definition + else: + # this is a real class that needs to be applied upon + # the base Components + for attr_name in dir(base): + attr = getattr(base, attr_name, None) + if not getattr(attr, "is_mapping", None): + continue + has_only_create = getattr(attr, "only_create", False) + mapping_changed_by = set(getattr(attr, "changed_by", ())) + + # if already existing, it has been defined in an previous + # base, extend the @changed_by set + if map_methods.get(attr_name) is not None: + definition = map_methods[attr_name] + mapping_changed_by.update(definition.changed_by) + + # keep the last choice for only_create + definition = MappingDefinition(mapping_changed_by, has_only_create) + map_methods[attr_name] = definition + + cls._map_methods = map_methods + + # pylint: disable=W8110 + @classmethod + def _complete_component_build(cls): + super()._complete_component_build() + cls._build_mapper_component() + + def __init__(self, work): + super().__init__(work) + self._options = None + + def _map_direct(self, record, from_attr, to_attr): + """Apply the ``direct`` mappings. + + :param record: record to convert from a source to a target + :param from_attr: name of the source attribute or a callable + :type from_attr: callable | str + :param to_attr: name of the target attribute + :type to_attr: str + """ + raise NotImplementedError + + def _map_children(self, record, attr, model): + raise NotImplementedError + + @property + def map_methods(self): + """Yield all the methods decorated with ``@mapping``""" + for meth, definition in self._map_methods.items(): + yield getattr(self, meth), definition + + def _get_map_child_component(self, model_name): + try: + mapper_child = self.component( + usage=self._map_child_usage, model_name=model_name + ) + except NoComponentError: + assert self._map_child_fallback is not None, "_map_child_fallback required" + # does not force developers to use a MapChild -> + # will use the default one if not explicitely defined + mapper_child = self.component_by_name( + self._map_child_fallback, model_name=model_name + ) + return mapper_child + + def _map_child(self, map_record, from_attr, to_attr, model_name): + """Convert items of the record as defined by children""" + assert self._map_child_usage is not None, "_map_child_usage required" + child_records = map_record.source[from_attr] + mapper_child = self._get_map_child_component(model_name) + items = mapper_child.get_items( + child_records, map_record, to_attr, options=self.options + ) + return items + + @contextmanager + def _mapping_options(self, options): + """Change the mapping options for the Mapper. + + Context Manager to use in order to alter the behavior + of the mapping, when using ``_apply`` or ``finalize``. + + """ + current = self._options + self._options = options + yield + self._options = current + + @property + def options(self): + """Options can be accessed in the mapping methods with + ``self.options``.""" + return self._options + + def changed_by_fields(self): + """Build a set of fields used by the mapper + + It takes in account the ``direct`` fields and the fields used by + the decorator: ``changed_by``. + """ + changed_by = set() + if getattr(self, "direct", None): + for from_attr, __ in self.direct: + fieldname = self._direct_source_field_name(from_attr) + changed_by.add(fieldname) + + for _method_name, method_def in self._map_methods.items(): + changed_by |= method_def.changed_by + return changed_by + + def _direct_source_field_name(self, direct_entry): + """Get the mapping field name. Goes through the function modifiers. + + Ex:: + + [(none(convert(field_name, str)), out_field_name)] + + It assumes that the modifier has ``field`` as first argument like:: + + def modifier(field, args): + + """ + fieldname = direct_entry + if callable(direct_entry): + # Map the closure entries with variable names + cells = dict( + list( + zip( + direct_entry.__code__.co_freevars, + (c.cell_contents for c in direct_entry.__closure__), + strict=True, + ) + ) + ) + assert "field" in cells, "Modifier without 'field' argument." + if callable(cells["field"]): + fieldname = self._direct_source_field_name(cells["field"]) + else: + fieldname = cells["field"] + return fieldname + + def map_record(self, record, parent=None): + """Get a :py:class:`MapRecord` with record, ready to be + converted using the current Mapper. + + :param record: record to transform + :param parent: optional parent record, for items + + """ + return MapRecord(self, record, parent=parent) + + def _apply(self, map_record, options=None): + """Apply the mappings on a :py:class:`MapRecord` + + :param map_record: source record to convert + :type map_record: :py:class:`MapRecord` + + """ + if options is None: + options = {} + with self._mapping_options(options): + return self._apply_with_options(map_record) + + def _apply_with_options(self, map_record): + """Apply the mappings on a :py:class:`MapRecord` with + contextual options (the ``options`` given in + :py:meth:`MapRecord.values()` are accessible in + ``self.options``) + + :param map_record: source record to convert + :type map_record: :py:class:`MapRecord` + + """ + assert ( + self.options is not None + ), "options should be defined with '_mapping_options'" + _logger.debug("converting record %s to model %s", map_record.source, self.model) + + fields = self.options.fields + for_create = self.options.for_create + result = {} + for from_attr, to_attr in self.direct: + if callable(from_attr): + attr_name = self._direct_source_field_name(from_attr) + else: + attr_name = from_attr + + if not fields or attr_name in fields: + value = self._map_direct(map_record.source, from_attr, to_attr) + result[to_attr] = value + + for meth, definition in self.map_methods: + mapping_changed_by = definition.changed_by + if ( + not fields + or not mapping_changed_by + or mapping_changed_by.intersection(fields) + ): + if definition.only_create and not for_create: + continue + values = meth(map_record.source) + if not values: + continue + if not isinstance(values, dict): + raise ValueError( + f"{values}: invalid return value for the " + f"mapping method {meth}" + ) + result.update(values) + + for from_attr, to_attr, model_name in self.children: + if not fields or from_attr in fields: + result[to_attr] = self._map_child( + map_record, from_attr, to_attr, model_name + ) + + return self.finalize(map_record, result) + + def finalize(self, map_record, values): + """Called at the end of the mapping. + + Can be used to modify the values generated by all the mappings before + returning them. + + :param map_record: source map_record + :type map_record: :py:class:`MapRecord` + :param values: mapped values + :returns: mapped values + :rtype: dict + """ + return values + + +class ImportMapper(AbstractComponent): + """:py:class:`Mapper` for imports. + + Transform a record from a backend to an Odoo record + + """ + + _name = "base.import.mapper" + _inherit = "base.mapper" + _usage = "import.mapper" + + _map_child_usage = "import.map.child" + _map_child_fallback = "base.map.child.import" + + def _map_direct(self, record, from_attr, to_attr): + """Apply the ``direct`` mappings. + + :param record: record to convert from a source to a target + :param from_attr: name of the source attribute or a callable + :type from_attr: callable | str + :param to_attr: name of the target attribute + :type to_attr: str + """ + if callable(from_attr): + return from_attr(self, record, to_attr) + + value = record.get(from_attr) + if not value: + return False + + # Backward compatibility: when a field is a relation, and a modifier is + # not used, we assume that the relation model is a binding. + # Use an explicit modifier external_to_m2o in the 'direct' mappings to + # change that. + field = self.model._fields[to_attr] + if field.type == "many2one": + mapping_func = external_to_m2o(from_attr) + value = mapping_func(self, record, to_attr) + return value + + +class ExportMapper(AbstractComponent): + """:py:class:`Mapper` for exports. + + Transform a record from Odoo to a backend record + + """ + + _name = "base.export.mapper" + _inherit = "base.mapper" + _usage = "export.mapper" + + _map_child_usage = "export.map.child" + _map_child_fallback = "base.map.child.export" + + def _map_direct(self, record, from_attr, to_attr): + """Apply the ``direct`` mappings. + + :param record: record to convert from a source to a target + :param from_attr: name of the source attribute or a callable + :type from_attr: callable | str + :param to_attr: name of the target attribute + :type to_attr: str + """ + if callable(from_attr): + return from_attr(self, record, to_attr) + + value = record[from_attr] + if not value: + return False + + # Backward compatibility: when a field is a relation, and a modifier is + # not used, we assume that the relation model is a binding. + # Use an explicit modifier m2o_to_external in the 'direct' mappings to + # change that. + field = self.model._fields[from_attr] + if field.type == "many2one": + mapping_func = m2o_to_external(from_attr) + value = mapping_func(self, record, to_attr) + return value + + +class MapRecord: + """A record prepared to be converted using a :py:class:`Mapper`. + + MapRecord instances are prepared by :py:meth:`Mapper.map_record`. + + Usage:: + + >>> map_record = mapper.map_record(record) + >>> output_values = map_record.values() + + See :py:meth:`values` for more information on the available arguments. + + """ + + def __init__(self, mapper, source, parent=None): + self._source = source + self._mapper = mapper + self._parent = parent + self._forced_values = {} + + @property + def source(self): + """Source record to be converted""" + return self._source + + @property + def parent(self): + """Parent record if the current record is an item""" + return self._parent + + def values(self, for_create=None, fields=None, **kwargs): + """Build and returns the mapped values according to the options. + + Usage:: + + >>> map_record = mapper.map_record(record) + >>> output_values = map_record.values() + + Creation of records + When using the option ``for_create``, only the mappings decorated + with ``@only_create`` will be mapped. + + :: + + >>> output_values = map_record.values(for_create=True) + + Filter on fields + When using the ``fields`` argument, the mappings will be + filtered using either the source key in ``direct`` arguments, + either the ``changed_by`` arguments for the mapping methods. + + :: + + >>> output_values = map_record.values( + fields=['name', 'street'] + ) + + Custom options + Arbitrary key and values can be defined in the ``kwargs`` + arguments. They can later be used in the mapping methods + using ``self.options``. + + :: + + >>> output_values = map_record.values(tax_include=True) + + :param for_create: specify if only the mappings for creation + (``@only_create``) should be mapped. + :type for_create: boolean + :param fields: filter on fields + :type fields: list + :param ``**kwargs``: custom options, they can later be used in the + mapping methods + + """ + options = MapOptions(for_create=for_create, fields=fields, **kwargs) + values = self._mapper._apply(self, options=options) + values.update(self._forced_values) + return values + + def update(self, *args, **kwargs): + """Force values to be applied after a mapping. + + Usage:: + + >>> map_record = mapper.map_record(record) + >>> map_record.update(a=1) + >>> output_values = map_record.values() + # output_values will at least contain {'a': 1} + + The values assigned with ``update()`` are in any case applied, + they have a greater priority than the mapping values. + + """ + self._forced_values.update(*args, **kwargs) + + +class MapOptions(dict): + """Container for the options of mappings. + + Options can be accessed using attributes of the instance. When an + option is accessed and does not exist, it returns None. + + """ + + def __getitem__(self, key): + try: + return super().__getitem__(key) + except KeyError: + return None + + def __getattr__(self, key): + return self[key] + + def __setattr__(self, key, value): + self[key] = value diff --git a/connector/components/synchronizer.py b/connector/components/synchronizer.py new file mode 100644 index 000000000..07e8696f7 --- /dev/null +++ b/connector/components/synchronizer.py @@ -0,0 +1,447 @@ +# Copyright 2013 Camptocamp SA +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html) + +""" + +Synchronizer +============ + +A synchronizer orchestrates a synchronization with a backend. It's the actor +who runs the flow and glues the logic of an import or export (or else). +It uses other components for specialized tasks. + +For instance, it will use the mappings to convert the data between both +systems, the backend adapters to read or write data on the backend and the +binders to create the link between them. + +""" + +import logging +from contextlib import contextmanager + +import psycopg2 + +import odoo +from odoo import _ + +from odoo.addons.component.core import AbstractComponent + +from ..exception import IDMissingInBackend, RetryableJobError + +_logger = logging.getLogger(__name__) + + +class Synchronizer(AbstractComponent): + """Base class for synchronizers""" + + _name = "base.synchronizer" + _inherit = "base.connector" + + #: usage of the component used as mapper, can be customized in sub-classes + _base_mapper_usage = "mapper" + #: usage of the component used as backend adapter, + #: can be customized in sub-classes + _base_backend_adapter_usage = "backend.adapter" + + def __init__(self, work_context): + super().__init__(work_context) + self._backend_adapter = None + self._binder = None + self._mapper = None + + def run(self): + """Run the synchronization""" + raise NotImplementedError + + @property + def mapper(self): + """Return an instance of ``Mapper`` for the synchronization. + + The instantiation is delayed because some synchronizations do + not need such an unit and the unit may not exist. + + It looks for a Component with ``_usage`` being equal to + ``_base_mapper_usage``. + + :rtype: :py:class:`odoo.addons.component.core.Component` + """ + if self._mapper is None: + self._mapper = self.component(usage=self._base_mapper_usage) + return self._mapper + + @property + def binder(self): + """Return an instance of ``Binder`` for the synchronization. + + The instantiations is delayed because some synchronizations do + not need such an unit and the unit may not exist. + + :rtype: :py:class:`odoo.addons.component.core.Component` + """ + if self._binder is None: + self._binder = self.binder_for() + return self._binder + + @property + def backend_adapter(self): + """Return an instance of ``BackendAdapter`` for the + synchronization. + + The instantiations is delayed because some synchronizations do + not need such an unit and the unit may not exist. + + It looks for a Component with ``_usage`` being equal to + ``_base_backend_adapter_usage``. + + :rtype: :py:class:`odoo.addons.component.core.Component` + """ + if self._backend_adapter is None: + self._backend_adapter = self.component( + usage=self._base_backend_adapter_usage + ) + return self._backend_adapter + + +class Exporter(AbstractComponent): + """Synchronizer for exporting data from Odoo to a backend""" + + _name = "base.exporter" + _inherit = "base.synchronizer" + _usage = "exporter" + #: usage of the component used as mapper, can be customized in sub-classes + _base_mapper_usage = "export.mapper" + + +class GenericExporter(AbstractComponent): + """Generic Synchronizer for exporting data from Odoo to a backend""" + + _name = "generic.exporter" + _inherit = "base.exporter" + _default_binding_field = None + + def __init__(self, working_context): + super().__init__(working_context) + self.binding = None + self.external_id = None + + def _should_import(self): + return False + + def _delay_import(self): + """Schedule an import of the record. + + Adapt in the sub-classes when the model is not imported + using ``import_record``. + """ + # force is True because the sync_date will be more recent + # so the import would be skipped + assert self.external_id + self.binding.with_delay().import_record( + self.backend_record, self.external_id, force=True + ) + + def run(self, binding, *args, **kwargs): + """Run the synchronization + + :param binding: binding record to export + """ + self.binding = binding + + self.external_id = self.binder.to_external(self.binding) + try: + should_import = self._should_import() + except IDMissingInBackend: + self.external_id = None + should_import = False + if should_import: + self._delay_import() + + result = self._run(*args, **kwargs) + + self.binder.bind(self.external_id, self.binding) + # Commit so we keep the external ID when there are several + # exports (due to dependencies) and one of them fails. + # The commit will also release the lock acquired on the binding + # record + if not odoo.tools.config["test_enable"]: + self.env.cr.commit() # pylint: disable=E8102 + + self._after_export() + return result + + def _run(self, fields=None): + """Flow of the synchronization, implemented in inherited classes""" + assert self.binding + + if not self.external_id: + fields = None # should be created with all the fields + + if self._has_to_skip(): + return + + # export the missing linked resources + self._export_dependencies() + + # prevent other jobs to export the same record + # will be released on commit (or rollback) + self._lock() + + map_record = self._map_data() + + if self.external_id: + record = self._update_data(map_record, fields=fields) + if not record: + return _("Nothing to export.") + self._update(record) + else: + record = self._create_data(map_record, fields=fields) + if not record: + return _("Nothing to export.") + self.external_id = self._create(record) + return _("Record exported with ID %s on Backend.") % self.external_id + + def _after_export(self): + """Can do several actions after exporting a record on the backend""" + + def _lock(self): + """Lock the binding record. + + Lock the binding record so we are sure that only one export + job is running for this record if concurrent jobs have to export the + same record. + + When concurrent jobs try to export the same record, the first one + will lock and proceed, the others will fail to lock and will be + retried later. + + This behavior works also when the export becomes multilevel + with :meth:`_export_dependencies`. Each level will set its own lock + on the binding record it has to export. + + """ + sql = f"SELECT id FROM {self.model._table} WHERE ID = %s FOR UPDATE NOWAIT" + try: + self.env.cr.execute(sql, (self.binding.id,), log_exceptions=False) + except psycopg2.OperationalError as err: + _logger.info( + "A concurrent job is already exporting the same " + "record (%s with id %s). Job delayed later.", + self.model._name, + self.binding.id, + ) + raise RetryableJobError( + "A concurrent job is already exporting the same record " + f"({self.model._name} with id {self.binding.id}). The job will be " + f"retried later." + ) from err + + def _has_to_skip(self): + """Return True if the export can be skipped""" + return False + + @contextmanager + def _retry_unique_violation(self): + """Context manager: catch Unique constraint error and retry the + job later. + + When we execute several jobs workers concurrently, it happens + that 2 jobs are creating the same record at the same time (binding + record created by :meth:`_export_dependency`), resulting in: + + IntegrityError: duplicate key value violates unique + constraint "my_backend_product_product_odoo_uniq" + DETAIL: Key (backend_id, odoo_id)=(1, 4851) already exists. + + In that case, we'll retry the import just later. + + .. warning:: The unique constraint must be created on the + binding record to prevent 2 bindings to be created + for the same External record. + + """ + try: + yield + except psycopg2.IntegrityError as err: + if err.pgcode == psycopg2.errorcodes.UNIQUE_VIOLATION: + raise RetryableJobError( + "A database error caused the failure of the job:\n" + f"{err}\n\n" + "Likely due to 2 concurrent jobs wanting to create " + "the same record. The job will be retried later." + ) from err + else: + raise + + def _export_dependency( + self, + relation, + binding_model, + component_usage="record.exporter", + binding_field=None, + binding_extra_vals=None, + ): + """ + Export a dependency. The exporter class is a subclass of + ``GenericExporter``. If a more precise class need to be defined, + it can be passed to the ``exporter_class`` keyword argument. + + .. warning:: a commit is done at the end of the export of each + dependency. The reason for that is that we pushed a record + on the backend and we absolutely have to keep its ID. + + So you *must* take care not to modify the Odoo + database during an export, excepted when writing + back the external ID or eventually to store + external data that we have to keep on this side. + + You should call this method only at the beginning + of the exporter synchronization, + in :meth:`~._export_dependencies`. + + :param relation: record to export if not already exported + :type relation: :py:class:`odoo.models.BaseModel` + :param binding_model: name of the binding model for the relation + :type binding_model: str | unicode + :param component_usage: 'usage' to look for to find the Component to + for the export, by default 'record.exporter' + :type exporter: str | unicode + :param binding_field: name of the one2many field on a normal + record that points to the binding record + (default: my_backend_bind_ids). + It is used only when the relation is not + a binding but is a normal record. + :type binding_field: str | unicode + :binding_extra_vals: In case we want to create a new binding + pass extra values for this binding + :type binding_extra_vals: dict + """ + if binding_field is None: + binding_field = self._default_binding_field + if not relation: + return + rel_binder = self.binder_for(binding_model) + # wrap is typically True if the relation is for instance a + # 'product.product' record but the binding model is + # 'my_bakend.product.product' + wrap = relation._name != binding_model + + if wrap and hasattr(relation, binding_field): + domain = [ + ("odoo_id", "=", relation.id), + ("backend_id", "=", self.backend_record.id), + ] + binding = self.env[binding_model].search(domain) + if binding: + assert len(binding) == 1, ( + "only 1 binding for a backend is " "supported in _export_dependency" + ) + # we are working with a unwrapped record (e.g. + # product.category) and the binding does not exist yet. + # Example: I created a product.product and its binding + # my_backend.product.product and we are exporting it, but we need + # to create the binding for the product.category on which it + # depends. + else: + bind_values = { + "backend_id": self.backend_record.id, + "odoo_id": relation.id, + } + if binding_extra_vals: + bind_values.update(binding_extra_vals) + # If 2 jobs create it at the same time, retry + # one later. A unique constraint (backend_id, + # odoo_id) should exist on the binding model + with self._retry_unique_violation(): + binding = ( + self.env[binding_model] + .with_context(connector_no_export=True) + .sudo() + .create(bind_values) + ) + # Eager commit to avoid having 2 jobs + # exporting at the same time. The constraint + # will pop if an other job already created + # the same binding. It will be caught and + # raise a RetryableJobError. + if not odoo.tools.config["test_enable"]: + self.env.cr.commit() # pylint: disable=E8102 + else: + # If my_backend_bind_ids does not exist we are typically in a + # "direct" binding (the binding record is the same record). + # If wrap is True, relation is already a binding record. + binding = relation + + if not rel_binder.to_external(binding): + exporter = self.component(usage=component_usage, model_name=binding_model) + exporter.run(binding) + + def _export_dependencies(self): + """Export the dependencies for the record""" + return + + def _map_data(self): + """Returns an instance of + :py:class:`~odoo.addons.connector.components.mapper.MapRecord` + + """ + return self.mapper.map_record(self.binding) + + def _validate_create_data(self, data): + """Check if the values to import are correct + + Pro-actively check before the ``Model.create`` if some fields + are missing or invalid + + Raise `InvalidDataError` + """ + return + + def _validate_update_data(self, data): + """Check if the values to import are correct + + Pro-actively check before the ``Model.update`` if some fields + are missing or invalid + + Raise `InvalidDataError` + """ + return + + def _create_data(self, map_record, fields=None, **kwargs): + """Get the data to pass to :py:meth:`_create`""" + return map_record.values(for_create=True, fields=fields, **kwargs) + + def _create(self, data): + """Create the External record""" + # special check on data before export + self._validate_create_data(data) + return self.backend_adapter.create(data) + + def _update_data(self, map_record, fields=None, **kwargs): + """Get the data to pass to :py:meth:`_update`""" + return map_record.values(fields=fields, **kwargs) + + def _update(self, data): + """Update an External record""" + assert self.external_id + # special check on data before export + self._validate_update_data(data) + self.backend_adapter.write(self.external_id, data) + + +class Importer(AbstractComponent): + """Synchronizer for importing data from a backend to Odoo""" + + _name = "base.importer" + _inherit = "base.synchronizer" + _usage = "importer" + #: usage of the component used as mapper, can be customized in sub-classes + _base_mapper_usage = "import.mapper" + + +class Deleter(AbstractComponent): + """Synchronizer for deleting a record on the backend""" + + _name = "base.deleter" + _inherit = "base.synchronizer" + #: usage of the component used as mapper, can be customized in sub-classes + _usage = "deleter" diff --git a/connector/database.py b/connector/database.py new file mode 100644 index 000000000..6b3134f9b --- /dev/null +++ b/connector/database.py @@ -0,0 +1,78 @@ +# Copyright 2013 Camptocamp SA +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html) + +import hashlib +import logging +import struct + +_logger = logging.getLogger(__name__) + + +def pg_try_advisory_lock(env, lock): + """Try to acquire a Postgres transactional advisory lock. + + The function tries to acquire a lock, returns a boolean indicating + if it could be obtained or not. An acquired lock is released at the + end of the transaction. + + A typical use is to acquire a lock at the beginning of an importer + to prevent 2 jobs to do the same import at the same time. Since the + record doesn't exist yet, we can't put a lock on a record, so we put + an advisory lock. + + Example: + - Job 1 imports Partner A + - Job 2 imports Partner B + - Partner A has a category X which happens not to exist yet + - Partner B has a category X which happens not to exist yet + - Job 1 import category X as a dependency + - Job 2 import category X as a dependency + + Since both jobs are executed concurrently, they both create a record + for category X so we have duplicated records. With this lock: + + - Job 1 imports Partner A, it acquires a lock for this partner + - Job 2 imports Partner B, it acquires a lock for this partner + - Partner A has a category X which happens not to exist yet + - Partner B has a category X which happens not to exist yet + - Job 1 import category X as a dependency, it acquires a lock for + this category + - Job 2 import category X as a dependency, try to acquire a lock + but can't, Job 2 is retried later, and when it is retried, it + sees the category X created by Job 1. + + The lock is acquired until the end of the transaction. + + Usage example: + + :: + + lock_name = 'import_record({}, {}, {}, {})'.format( + self.backend_record._name, + self.backend_record.id, + self.model._name, + self.external_id, + ) + if pg_try_advisory_lock(lock_name): + # do sync + else: + raise RetryableJobError('Could not acquire advisory lock', + seconds=2, + ignore_retry=True) + + :param env: the Odoo Environment + :param lock: The lock name. Can be anything convertible to a + string. It needs to represents what should not be synchronized + concurrently so usually the string will contain at least: the + action, the backend type, the backend id, the model name, the + external id + :return True/False whether lock was acquired. + """ + hasher = hashlib.sha1(str(lock).encode()) + # pg_lock accepts an int8 so we build an hash composed with + # contextual information and we throw away some bits + int_lock = struct.unpack("q", hasher.digest()[:8]) + + env.cr.execute("SELECT pg_try_advisory_xact_lock(%s);", (int_lock,)) + acquired = env.cr.fetchone()[0] + return acquired diff --git a/connector/doc/Makefile b/connector/doc/Makefile new file mode 100644 index 000000000..58156b0cf --- /dev/null +++ b/connector/doc/Makefile @@ -0,0 +1,153 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = _build + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + -rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Connectors.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Connectors.qhc" + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/Connectors" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Connectors" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." diff --git a/connector/doc/_static/09_datamodel.png b/connector/doc/_static/09_datamodel.png new file mode 100644 index 000000000..4bf0bee34 Binary files /dev/null and b/connector/doc/_static/09_datamodel.png differ diff --git a/connector/doc/_static/connector_style.css b/connector/doc/_static/connector_style.css new file mode 100644 index 000000000..7094ffcea --- /dev/null +++ b/connector/doc/_static/connector_style.css @@ -0,0 +1,3 @@ +.navbar span.navbar-text { + visibility: hidden; +} diff --git a/connector/doc/_static/img/LogicSupply_Orange_260x80_transparent.png b/connector/doc/_static/img/LogicSupply_Orange_260x80_transparent.png new file mode 100644 index 000000000..046f4ee83 Binary files /dev/null and b/connector/doc/_static/img/LogicSupply_Orange_260x80_transparent.png differ diff --git a/connector/doc/_static/img/akretion_logo.png b/connector/doc/_static/img/akretion_logo.png new file mode 100644 index 000000000..6b298965d Binary files /dev/null and b/connector/doc/_static/img/akretion_logo.png differ diff --git a/connector/doc/_static/img/c2c_square_baseline_192.jpg b/connector/doc/_static/img/c2c_square_baseline_192.jpg new file mode 100644 index 000000000..1b3d6b620 Binary files /dev/null and b/connector/doc/_static/img/c2c_square_baseline_192.jpg differ diff --git a/connector/doc/_static/img/logo-debonix.jpg b/connector/doc/_static/img/logo-debonix.jpg new file mode 100644 index 000000000..9986555d3 Binary files /dev/null and b/connector/doc/_static/img/logo-debonix.jpg differ diff --git a/connector/doc/_static/img/magentoerpconnect.png b/connector/doc/_static/img/magentoerpconnect.png new file mode 100644 index 000000000..8480511a6 Binary files /dev/null and b/connector/doc/_static/img/magentoerpconnect.png differ diff --git a/connector/doc/_static/img/magentoerpconnect150.png b/connector/doc/_static/img/magentoerpconnect150.png new file mode 100644 index 000000000..3f59d00b8 Binary files /dev/null and b/connector/doc/_static/img/magentoerpconnect150.png differ diff --git a/connector/doc/_static/img/prestashoperpconnect.png b/connector/doc/_static/img/prestashoperpconnect.png new file mode 100644 index 000000000..288ea7690 Binary files /dev/null and b/connector/doc/_static/img/prestashoperpconnect.png differ diff --git a/connector/doc/_static/img/prestashoperpconnect150.png b/connector/doc/_static/img/prestashoperpconnect150.png new file mode 100644 index 000000000..30f407eda Binary files /dev/null and b/connector/doc/_static/img/prestashoperpconnect150.png differ diff --git a/connector/doc/_templates/layout.html b/connector/doc/_templates/layout.html new file mode 100644 index 000000000..dad975cbf --- /dev/null +++ b/connector/doc/_templates/layout.html @@ -0,0 +1,20 @@ +{% extends "!layout.html" %} {%- block extrahead %} {{ super() }} + +{% endblock %} diff --git a/connector/doc/_templates/navbar.html b/connector/doc/_templates/navbar.html new file mode 100644 index 000000000..30dba850e --- /dev/null +++ b/connector/doc/_templates/navbar.html @@ -0,0 +1,28 @@ +{% extends "!navbar.html" %} {% block navbartoc %} + + +{{ super() }} {% endblock %} diff --git a/connector/doc/_themes/.gitignore b/connector/doc/_themes/.gitignore new file mode 100644 index 000000000..66b6e4c2f --- /dev/null +++ b/connector/doc/_themes/.gitignore @@ -0,0 +1,3 @@ +*.pyc +*.pyo +.DS_Store diff --git a/connector/doc/api/api_backend.rst b/connector/doc/api/api_backend.rst new file mode 100644 index 000000000..b4c11a543 --- /dev/null +++ b/connector/doc/api/api_backend.rst @@ -0,0 +1,24 @@ +###### +Models +###### + +.. _api-backend-model: + +************* +Backend Model +************* + + +.. autoclass:: connector.models.backend_model.ConnectorBackend + :members: + :undoc-members: + :show-inheritance: + +.. _api-binding-model: + +************* +Binding Model +************* + +.. autoclass:: connector.models.backend_model.ExternalBinding + :show-inheritance: diff --git a/connector/doc/api/api_channels.rst b/connector/doc/api/api_channels.rst new file mode 100644 index 000000000..8c06bd32b --- /dev/null +++ b/connector/doc/api/api_channels.rst @@ -0,0 +1,13 @@ +######## +Channels +######## + +This is the API documentation for the job channels and the +scheduling mechanisms of the job runner. + +These classes are not intended for use by module developers. + +.. automodule:: odoo.addons.queue_job.jobrunner.channels + :members: + :undoc-members: + :show-inheritance: diff --git a/connector/doc/api/api_components.rst b/connector/doc/api/api_components.rst new file mode 100644 index 000000000..9bfdd9479 --- /dev/null +++ b/connector/doc/api/api_components.rst @@ -0,0 +1,165 @@ +.. _api-component: + +########## +Components +########## + +Components are the blocks allowing to build a flexible and +well decoupled code. They are based on the ``component`` addon, which +can as well be used separately. + + +*************** +Core Components +*************** + +.. automodule:: connector.components.core + :members: + :undoc-members: + :exclude-members: _module + :show-inheritance: + :private-members: + + +******************** +Connector Components +******************** + +.. automodule:: connector.components.binder + :members: + :undoc-members: + :exclude-members: _module + :show-inheritance: + :private-members: + +.. automodule:: connector.components.mapper + :members: + :member-order: groupwise + :exclude-members: MappingDefinition, Mapper, ImportMapper, ExportMapper, MapChild, ImportMapChild, ExportMapChild + :show-inheritance: + + .. autoclass:: Mapper + :members: + :show-inheritance: + + .. autoattribute:: _name + .. autoattribute:: _inherit + .. autoattribute:: _usage + + .. autoclass:: ImportMapper + :members: + :show-inheritance: + + .. autoattribute:: _name + .. autoattribute:: _inherit + .. autoattribute:: _usage + + .. autoclass:: ExportMapper + :members: + :show-inheritance: + + .. autoattribute:: _name + .. autoattribute:: _inherit + .. autoattribute:: _usage + + .. autoclass:: MapChild + :members: + :show-inheritance: + + .. autoattribute:: _name + .. autoattribute:: _inherit + .. autoattribute:: _usage + + .. autoclass:: ImportMapChild + :members: + :show-inheritance: + + .. autoattribute:: _name + .. autoattribute:: _inherit + .. autoattribute:: _usage + + .. autoclass:: ExportMapChild + :members: + :show-inheritance: + + .. autoattribute:: _name + .. autoattribute:: _inherit + .. autoattribute:: _usage + + +.. automodule:: connector.components.backend_adapter + :members: + :show-inheritance: + :exclude-members: BackendAdapter, CRUDAdapter + + .. autoclass:: BackendAdapter + :members: + :show-inheritance: + + .. autoattribute:: _name + .. autoattribute:: _inherit + .. autoattribute:: _usage + + .. autoclass:: CRUDAdapter + :members: + :show-inheritance: + + .. autoattribute:: _name + .. autoattribute:: _inherit + .. autoattribute:: _usage + +.. automodule:: connector.components.synchronizer + :members: + :undoc-members: + :show-inheritance: + :exclude-members: _module + :private-members: + +.. automodule:: connector.components.listener + :members: + :undoc-members: + :show-inheritance: + :exclude-members: _module + :private-members: + +.. automodule:: connector.components.locker + :members: + :undoc-members: + :show-inheritance: + :exclude-members: _module + :private-members: + +*************************** +Components Collection Model +*************************** + +.. automodule:: odoo.addons.component.models.collection + :members: + :undoc-members: + :show-inheritance: + + +********************* +Components Exceptions +********************* + +.. automodule:: odoo.addons.component.exception + :members: + :undoc-members: + :show-inheritance: + +******************** +Components Internals +******************** + +Low-level APIs of the Components. + +.. automodule:: odoo.addons.component.core + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: odoo.addons.component.builder + :members: + :undoc-members: + :show-inheritance: diff --git a/connector/doc/api/api_event.rst b/connector/doc/api/api_event.rst new file mode 100644 index 000000000..4d7aa2b0a --- /dev/null +++ b/connector/doc/api/api_event.rst @@ -0,0 +1,26 @@ +.. _api-event: + +###### +Events +###### + +Events is an implementation of an Observer pattern for Odoo. + + +********** +Components +********** + +.. automodule:: odoo.addons.component_event.components.event + :members: + :show-inheritance: + + +********************** +Odoo Models Extensions +********************** + +.. automodule:: odoo.addons.component_event.models.base + + .. autoclass:: Base + :show-inheritance: diff --git a/connector/doc/api/api_exception.rst b/connector/doc/api/api_exception.rst new file mode 100644 index 000000000..2b8d4be6d --- /dev/null +++ b/connector/doc/api/api_exception.rst @@ -0,0 +1,7 @@ +Exceptions +========== + +.. automodule:: connector.exception + :members: + :undoc-members: + :show-inheritance: diff --git a/connector/doc/api/api_queue.rst b/connector/doc/api/api_queue.rst new file mode 100644 index 000000000..a59309ec6 --- /dev/null +++ b/connector/doc/api/api_queue.rst @@ -0,0 +1,45 @@ +.. _api-queue: + +##### +Queue +##### + +Models +****** + +.. automodule:: odoo.addons.queue_job.models.base + :members: + :undoc-members: + :show-inheritance: + +.. automodule:: odoo.addons.queue_job.models.queue_job + + .. autoclass:: QueueJob + + .. autoattribute:: _name + .. autoattribute:: _inherit + +*** +Job +*** + +.. automodule:: odoo.addons.queue_job.job + + Decorators + ========== + + .. autofunction:: job + .. autofunction:: related_action + + Internals + ========= + + .. autoclass:: DelayableRecordset + :members: + :undoc-members: + :show-inheritance: + + .. autoclass:: Job + :members: + :undoc-members: + :show-inheritance: diff --git a/connector/doc/bazaar b/connector/doc/bazaar new file mode 100644 index 000000000..be7f109f9 --- /dev/null +++ b/connector/doc/bazaar @@ -0,0 +1,27 @@ +# This viminfo file was generated by Vim 7.4. +# You may edit it if you're careful! + +# Value of 'encoding' when this file was written +*encoding=utf-8 + + +# hlsearch on (H) or off (h): +~h +# Command Line History (newest to oldest): +:q! + +# Search String History (newest to oldest): + +# Expression History (newest to oldest): + +# Input Line History (newest to oldest): + +# Input Line History (newest to oldest): + +# Registers: + +# File marks: + +# Jumplist (newest first): + +# History of marks within files (newest to oldest): diff --git a/connector/doc/conf.py b/connector/doc/conf.py new file mode 100644 index 000000000..c8b4607a8 --- /dev/null +++ b/connector/doc/conf.py @@ -0,0 +1,376 @@ +# +# Connectors documentation build configuration file, created by +# sphinx-quickstart on Mon Feb 4 11:35:44 2013. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +# flake8: noqa + +import os +import sys + +import sphinx_bootstrap_theme + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# sys.path.insert(0, os.path.abspath('.')) +sys.path.append(os.path.abspath("_themes")) + +MANIFEST_FILES = ["__manifest__.py", "__odoo__.py", "__openerp__.py"] + + +def is_module(path): + """return False if the path doesn't contain an odoo module, and the full + path to the module manifest otherwise""" + + if not os.path.isdir(path): + return False + files = os.listdir(path) + filtered = [x for x in files if x in (MANIFEST_FILES + ["__init__.py"])] + if len(filtered) == 2 and "__init__.py" in filtered: + return os.path.join(path, next(x for x in filtered if x != "__init__.py")) + else: + return False + + +def is_installable_module(path): + """return False if the path doesn't contain an installable odoo module, + and the full path to the module manifest otherwise""" + manifest_path = is_module(path) + if manifest_path: + manifest = ast.literal_eval(open(manifest_path).read()) + if manifest.get("installable", True): + return manifest_path + return False + + +if os.environ.get("TRAVIS_BUILD_DIR") and os.environ.get("VERSION"): + # build from travis + repos_home = os.environ["HOME"] + deps_path = os.path.join(repos_home, "dependencies") + odoo_folder = "odoo-" + os.environ.get("VERSION") + odoo_root = os.path.join(repos_home, odoo_folder) + build_path = os.environ["TRAVIS_BUILD_DIR"] +else: + # build from dev + odoo_root = os.path.abspath("../../../../src") + deps_path = os.path.abspath("../../..") + build_path = os.path.abspath("../..") + +addons_paths = [] + + +def add_path(*paths): + addons_paths.append(os.path.join(*paths)) + + +add_path(odoo_root, "odoo", "addons") +add_path(odoo_root, "addons") +add_path(build_path) + +deps_repos = [ + repo + for repo in os.listdir(deps_path) + if os.path.isdir(os.path.join(deps_path, repo)) and not repo.startswith(".") +] + +for repo in deps_repos: + add_path(deps_path, repo) + +addons = [ + x + for x in os.listdir(build_path) + if not x.startswith((".", "__")) and is_installable_module(x) +] + + +# sphinxodoo.ext.autodoc variables +sphinxodoo_root_path = odoo_root +sphinxodoo_addons = addons +sphinxodoo_addons_path = addons_paths +sys.path.append(build_path) + + +# -- General configuration ----------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +extensions = [ + "sphinx.ext.autodoc", + "sphinx.ext.intersphinx", + "sphinx.ext.todo", + "sphinx.ext.viewcode", + "sphinxodoo.ext.autodoc", +] + +todo_include_todos = False + +# Add any paths that contain templates here, relative to this directory. +templates_path = ["_templates"] + +# The suffix of source filenames. +source_suffix = ".rst" + +# The encoding of source files. +# source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = "index" + +# autodoc options +autodoc_member_order = "bysource" + +# General information about the project. +project = "Connector" +copyright = "2013, Camptocamp SA" # pylint: disable=W0622 + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = "" +# The full version, including alpha/beta/rc tags. +release = "" + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +language = "en" +locale_dirs = ["locale"] +gettext_compact = True + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +# today = '' +# Else, today_fmt is used as the format for a strftime call. +# today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ["_build"] + +# The reST default role (used for this markup: `text`) to use for all documents. +# default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +# add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +# add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +# show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = "sphinx" + +# A list of ignored prefixes for module index sorting. +# modindex_common_prefix = [] + + +# -- Options for HTML output --------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = "bootstrap" + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +html_theme_options = { + # Navigation bar title. (Default: ``project`` value) + "navbar_title": "Odoo Connector", + # Tab name for entire site. (Default: "Site") + "navbar_site_name": "Site", + # Global TOC depth for "site" navbar tab. (Default: 1) + # Switching to -1 shows all levels. + "globaltoc_depth": 2, + # Include hidden TOCs in Site navbar? + # + # Note: If this is "false", you cannot have mixed ``:hidden:`` and + # non-hidden ``toctree`` directives in the same page, or else the build + # will break. + # + # Values: "true" (default) or "false" + "globaltoc_includehidden": "true", + # HTML navbar class (Default: "navbar") to attach to
element. + # For black navbar, do "navbar navbar-inverse" + "navbar_class": "navbar", + # Fix navigation bar to top of page? + # Values: "true" (default) or "false" + "navbar_fixed_top": "true", + # Location of link to source. + # Options are "nav" (default), "footer" or anything else to exclude. + "source_link_position": "footer", + # Bootswatch (http://bootswatch.com/) theme. + # + # Options are nothing with "" (default) or the name of a valid theme + # such as "amelia" or "cosmo". + # + # Note that this is served off CDN, so won't be available offline. + "bootswatch_theme": "united", +} + +# Add any paths that contain custom themes here, relative to this directory. +html_theme_path = sphinx_bootstrap_theme.get_html_theme_path() + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +# html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +# html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +# html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +# html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ["_static"] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +# html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +# html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +# html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +# html_additional_pages = {} + +# If false, no module index is generated. +# html_domain_indices = True + +# If false, no index is generated. +# html_use_index = True + +# If true, the index is split into individual pages for each letter. +# html_split_index = False + +# If true, links to the reST sources are added to the pages. +# html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +# html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +# html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +# html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +# html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = "connector-doc" + + +# -- Options for LaTeX output -------------------------------------------- + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + #'papersize': 'letterpaper', + # The font size ('10pt', '11pt' or '12pt'). + #'pointsize': '10pt', + # Additional stuff for the LaTeX preamble. + #'preamble': '', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass [howto/manual]). +latex_documents = [ + ("index", "Connector.tex", "Connector Documentation", "Camptocamp SA", "manual") +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +# latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +# latex_use_parts = False + +# If true, show page references after internal links. +# latex_show_pagerefs = False + +# If true, show URL addresses after external links. +# latex_show_urls = False + +# Documents to append as an appendix to all manuals. +# latex_appendices = [] + +# If false, no module index is generated. +# latex_domain_indices = True + + +# -- Options for manual page output -------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [("index", "connector", "Connector Documentation", ["Camptocamp SA"], 1)] + +# If true, show URL addresses after external links. +# man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------ + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + ( + "index", + "Connector", + "Connector Documentation", + "Camptocamp SA", + "Connector", + "Framework for Odoo Connectors.", + "Miscellaneous", + ) +] + +# Documents to append as an appendix to all manuals. +# texinfo_appendices = [] + +# If false, no module index is generated. +# texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +# texinfo_show_urls = 'footnote' + + +# Example configuration for intersphinx: refer to the Python standard library. +intersphinx_mapping = { + "http://docs.python.org/": None, + "odooweb": ("https://www.odoo.com/documentation/10.0/", None), + "odoodev": ("https://www.odoo.com/documentation/10.0/", None), + "connectormagento": ("http://www.odoo-magento-connector.com", None), +} diff --git a/connector/doc/guides/bootstrap_connector.rst b/connector/doc/guides/bootstrap_connector.rst new file mode 100644 index 000000000..e69123800 --- /dev/null +++ b/connector/doc/guides/bootstrap_connector.rst @@ -0,0 +1,152 @@ +.. _bootstrap-connector: + + +######################## +Boostrapping a connector +######################## + +We'll see the steps to bootstrap a new connector. + +Besides that, you may want to use the existing connectors to have some +real implementation examples: + +* `Odoo Magento Connector`_ +* `Odoo Prestashop Connector`_ + +Be aware that the connector API has changed in Odoo 10.0, so the examples +might be outdated. + +Some boilerplate is necessary, so this document will guide you through +some steps. Please also take a look on the :ref:`naming-convention`. + +For the sake of the example, we'll imagine we have to synchronize +Odoo with a coffee machine. + +************* +Odoo Manifest +************* + +As we want to synchronize Odoo with a coffee machine, we'll name +our connector connector_coffee. + +First, we need to create the Odoo addons itself, editing the +``connector_coffee/__manifest__.py`` manifest. + + +.. code-block:: python + :emphasize-lines: 3,4 + + {'name': 'Coffee Connector', + 'version': '1.0.0', + 'category': 'Connector', + 'depends': ['connector', + ], + 'author': 'Myself', + 'license': 'LGPL-3', + 'description': """ + Coffee Connector + ================ + + Connect Odoo to my coffee machine. + + Features: + + * Pour a coffee when Odoo is busy for too long + """, + 'data': [], + 'installable': True, + } + +Nothing special but 2 things to note: + +* It depends from ``connector``. ``connector`` itself depends from + ``queue_job``, ``component`` and ``component_event``. ``queue_job`` is in the + `OCA/queue`_ repository. +* The module category should be ``Connector``. + +Of course, we also need to create the ``__init__.py`` file where we will +put the imports of our python modules. + +.. _OCA/queue: https://github.com/OCA/queue + + +************* +Backend Model +************* + +Reference: :ref:`api-backend-model` + +We need to create a Backend representing the external service. Every record we +synchronize will be linked with a record of ``coffee.backend``. This backend +is our *collection* of Components. + +The ``coffee.backend`` model is an ``_inherit`` of ``connector.backend``. In +``connector_coffee/models/coffee_binding.py``:: + + from odoo import api, fields, models + + + class CoffeeBackend(models.Model): + _name = 'coffee.backend' + _description = 'Coffee Backend' + _inherit = 'connector.backend' + + location = fields.Char(string='Location') + username = fields.Char(string='Username') + password = fields.Char(string='Password') + +Notes: + +* We can other fields for the configuration of the connection or the + synchronizations. + +**************** +Abstract Binding +**************** + +Reference: :ref:`api-binding-model` + +In order to share common features between all the bindings (see +:ref:`binding`), create an abstract binding model. + +It can be as follows (in ``connector_coffee/models/coffee_binding.py``):: + + from odoo import models, fields + + + class CoffeeBinding(models.AbstractModel): + _name = 'coffee.binding' + _inherit = 'external.binding' + _description = 'Coffee Binding (abstract)' + + # odoo_id = odoo-side id must be declared in concrete model + backend_id = fields.Many2one( + comodel_name='coffee.backend', + string='Coffee Backend', + required=True, + ondelete='restrict', + ) + coffee_id = fields.Integer(string='ID in the Coffee Machine', + index=True) + +Notes: + +* This model inherit from ``external.binding`` +* Any number of fields or methods can be added + + +********** +Components +********** + +Reference: :ref:`api-component` + +We'll probably need to create synchronizers, mappers, backend adapters, +binders and maybe our own kind of components. + +Their implementation can vary from a project to another. Have a look on the +`Odoo Magento Connector`_ and `Odoo Prestashop Connector`_ projects. + + +.. _`Odoo Magento Connector`: https://github.com/OCA/connector-magento +.. _`Odoo Prestashop Connector`: https://github.com/OCA/connector-prestashop diff --git a/connector/doc/guides/code_overview.rst b/connector/doc/guides/code_overview.rst new file mode 100644 index 000000000..3ecc22e6c --- /dev/null +++ b/connector/doc/guides/code_overview.rst @@ -0,0 +1,188 @@ +.. _code-overview: + +############# +Code Overview +############# + +Some simple code examples. + +*************************** +Trigger and listen an event +*************************** + +.. code-block:: python + + class AccountInvoice(models.Model): + _inherit = 'account.invoice' + + @api.multi + def action_invoice_paid(self): + res = super(AccountInvoice, self).action_invoice_paid() + for record in self: + self._event('on_invoice_paid').notify(record) + return res + + + +.. code-block:: python + + from odoo.addons.component.core import Component + + + class MyEventListener(Component): + _name = 'my.event.listener' + _inherit = 'base.event.listener' + + def on_invoice_paid(self, record): + _logger.info('invoice %s has been paid!', record.name) + +Ref: :ref:`api-event` + + +************************* +Delay an Asynchronous Job +************************* + +.. code-block:: python + + from odoo.addons.queue_job.job import job + + + class AccountInvoice(models.Model): + _inherit = 'account.invoice' + + @job + @api.multi + def export_payment(self): + self.ensure_one() + _logger.info("I'm exporting the payment for %s", self.name) + + @api.multi + def action_invoice_paid(self): + res = super(AccountInvoice, self).action_invoice_paid() + for record in self: + record.with_delay(priority=5).export_payment() + return res + +Ref: :ref:`api-queue` + +******************** +Work with components +******************** + +This is a highly simplified version of a micro-connector, without using +events or jobs, for the sake of the example. + +.. code-block:: python + + from odoo.addons.component.core import AbstractComponent + + + class MagentoBackend(models.Model): + _name = 'magento.backend' + _description = 'Magento Backend' + _inherit = 'connector.backend' + + location = fields.Char(string='Location', required=True) + username = fields.Char(string='Username') + password = fields.Char(string='Password') + + def import_partner(self, external_id): + with self.work_on(model_name='magento.res.partner') as work: + importer = work.component(usage='record.importer') + # returns an instance of PartnerImporter, which has been + # found with:the collection name (magento.backend, the model, + # and the usage). + importer.run(partner_id) + + # the next 2 components are abstract and are used by inheritance + # by the others + class BaseMagentoConnectorComponent(AbstractComponent): + # same inheritance than Odoo models + _name = 'base.magento.connector' + _inherit = 'base.connector' + # subscribe to: + _collection = 'magento.backend' + # the collection will be inherited to the components below, + # because they inherit from this component + + + class GenericAdapter(AbstractComponent): + # same inheritance than Odoo models + _name = 'magento.adapter' + _inherit = ['base.backend.adapter', 'base.magento.connector'] + # usage is used for lookups of components + _usage = 'backend.adapter' + + _magento_model = None + + def _call(self, *args, **kwargs): + location = self.backend_record.location + # use client API + + def read(self, fields=None): + """ Search records according to some criterias + and returns a list of ids + + :rtype: list + """ + return self._call('%s.info' % self._magento_model, fields) + + + # these are the components we need for our synchronization + class PartnerAdapter(Component): + _name = 'magento.partner.adapter' + _inherit = 'magento.adapter' + _apply_on = ['magento.res.partner'] + _magento_model = 'customer' + + + class PartnerMapper(Component): + _name = 'magento.partner.import.mapper' + _inherit = 'magento.import.mapper' # parent component omitted for brevity + _apply_on = ['magento.res.partner'] + _usage = 'import.mapper' + + + class PartnerBinder(Component): + _name = 'magento.partner.binder' + _inherit = 'magento.binder' # parent component omitted for brevity + _apply_on = ['magento.res.partner'] + _usage = 'binder' + + + class PartnerImporter(Component): + _name = 'magento.partner.importer' + _inherit = 'magento.importer' # parent component omitted for brevity + _apply_on = ['magento.res.partner'] + _usage = 'record.importer' + + def run(self, external_id): + # get the components we need for the sync + + # this one knows how to speak to magento + backend_adapter = self.component(usage='backend.adapter') + # this one knows how to convert magento data to odoo data + mapper = self.component(usage='import.mapper') + # this one knows how to link magento/odoo records + binder = self.component(usage='binder') + + # read external data from magento + external_data = backend_adapter.read(external_id) + # convert to odoo data + internal_data = mapper.map_record(external_data).values() + # find if the magento id already exists in odoo + binding = binder.to_internal(external_id) + if binding: + # if yes, we update it + binding.write(internal_data) + else: + # or we create it + binding = self.model.create(internal_data) + # finally, we bind both, so the next time we import + # the record, we'll update the same record instead of + # creating a new one + binder.bind(external_id, binding) + + +Ref: :ref:`api-component` diff --git a/connector/doc/guides/concepts.rst b/connector/doc/guides/concepts.rst new file mode 100644 index 000000000..5d0acb28d --- /dev/null +++ b/connector/doc/guides/concepts.rst @@ -0,0 +1,242 @@ +.. _concepts: + +################## +Connector Concepts +################## + +The framework to develop connectors is decoupled in small pieces of +codes interacting together. Each of them can be used or not in an +implementation. + +An example of implementation is the `Odoo Magento Connector`_. + +This document describes them from a high-level point of view and gives +pointers to more concrete 'how-to' or small tutorials. + +.. _`Odoo Magento Connector`: http://www.odoo-magento-connector.com + +****** +Events +****** + +Reference: :ref:`api-event` + +Events are hooks in Odoo on which we can plug some actions. They are +based on an Observer pattern. + +The same event can be shared across several connectors, easing their +implementation. +For instance, the module connector_ecommerce_ which extends the +framework with common e-commerce capabilities, adds its own events +common to e-commerce. + +A connectors developer is mostly interested by: + +* adding and listening to events (see :ref:`api-event`) + +.. _jobs-queue: + +********** +Jobs Queue +********** + +Reference: :ref:`api-queue` + +This feature is part of a standalone addon, but is a prerequisite for +the connector framework. + +The module is ``queue_job`` in https://github.com/OCA/queue. + +A connectors developer is mostly interested by: + +* Delay a job (see the decorator :py:func:`~odoo.addons.queue_job.job.job`) + + +******* +Backend +******* + +Reference: :ref:`api-backend-model` + +The Backend Model is what represents the external service / system we +synchronize with. The name on the backend indicates what is the collection the +Components will be registered into. Put another way: every backend has its own +collection of Components. + +It must use an ``_inherit`` on ``connector.backend``. + +``connector.backend`` inherits +:class:`odoo.addons.component.models.collection.Collection` which has a +:meth:`odoo.addons.component.models.collection.Collection.work_on` that will be +used as entrypoint for the component system. This method returns a +:class:`~odoo.addons.component.core.WorkContext` + +*********** +WorkContext +*********** + +Reference: :class:`~odoo.addons.component.core.WorkContext` + +A :class:`~odoo.addons.component.core.WorkContext` is the work environment or +context that will be passed transversally through all the components. This is +also the entrypoint to the component system. + +A connectors developer is mostly interested by: + +* Get a Component from a WorkContext (:py:meth:`~odoo.addons.component.core.WorkContext.component`) + +********* +Component +********* + +Reference: :ref:`api-component` + +:py:class:`~odoo.addons.component.core.Component` are pluggable classes used +for the synchronizations with the external systems (or anything!) + +The Components system has been extracted in a standalone addon (``component``), +which means it can really be used in a totally different way. + +The connector defines some base components, which you can find below. Note +that you can and are encouraged to define your own Components as well. + +Mappings +======== + +The base class is :py:class:`connector.components.mapper.Mapper`. + +In your components, you probably want to inherit from: + +* ``_inherit = 'base.import.mapper'`` +* ``_inherit = 'base.export.mapper'`` + +And the usages for the lookups are: + +* ``import.mapper`` +* ``export.mapper`` + +A mapping translates an external record to an Odoo record and +conversely. + +It supports: + +direct mappings + Fields *a* is written in field *b*. + +method mappings + A method is used to convert one or many fields to one or many + fields, with transformation. + It can be filtered, for example only applied when the record is + created or when the source fields are modified. + +submapping + a sub-record (lines of a sale order) is converted using another + Mapper + +See the documentation of the class for more details. + +Synchronizers +============= + +The base class is :py:class:`connector.components.synchronizer.Synchronizer`. + +In your components, you probably want to inherit from: + +* ``_inherit = 'base.importer'`` +* ``_inherit = 'base.exporter'`` + +And the usages for the lookups are: + +* ``importer`` +* ``exporter`` + +However, in your implementation, it is advised to use more refined usages such +as: + +* ``record.importer`` +* ``record.exporter`` +* ``batch.importer`` +* ``batch.exporter`` +* .. + +A synchronizer orchestrates a synchronization with a backend. It can be a +record's import or export, a deletion of something, or anything else. For +instance, it will use the mappings to convert the data between both systems, +the backend adapters to read or write data on the backend and the binders to +create the link between them. + +Backend Adapters +================ + +The base class is +:py:class:`connector.components.backend_adapter.BackendAdapter`. + +In your components, you probably want to inherit from: + +* ``_inherit = 'base.backend.adapter'`` +* ``_inherit = 'base.backend.adapter.crud'`` + +And the usages for the lookups are: + +* ``backend.adapter`` + +An external adapter has a common interface to speak with the backend. +It translates the basic orders (search, read, write) to the protocol +used by the backend. + +Binders +======= + +The base class is +:py:class:`connector.components.binder.Binder`. + +In your components, you probably want to inherit from: + +* ``_inherit = 'base.binder'`` + +And the usages for the lookups are: + +* ``binder`` + +Binders are components that know how to find the external ID for an +Odoo ID, how to find the Odoo ID for an external ID and how to +create the binding between them. A default implementation is +available and can be inherited if needed. + +Listeners +========= + +The base class is +:py:class:`connector.components.listener.ConnectorListener`. + +In your components, you probably want to inherit from: + +* ``_inherit = 'base.connector.listener'`` + +This is where you will register your event listeners. +See :mod:`addons.component_event.components.event`. + + +.. _binding: + +******** +Bindings +******** + +Reference: :ref:`api-binding-model` + +A binding represents the link of a record between Odoo and a backend. + +The proposed implementation for the connectors widely use the +`_inherits` capabilities. + +Say we import a customer from *Magento*. + +We create a `magento.res.partner` model, which `_inherits` +`res.partner`. + +This model, called a *binding* model, knows the ID of the partner in +Odoo, the ID in Magento and the relation to the backend model. + +It also stores all the necessary metadata related to this customer +coming from Magento. diff --git a/connector/doc/guides/jobrunner.rst b/connector/doc/guides/jobrunner.rst new file mode 100644 index 000000000..a078f996c --- /dev/null +++ b/connector/doc/guides/jobrunner.rst @@ -0,0 +1,39 @@ +.. _jobrunner: + + +####################################### +Configuring channels and the job runner +####################################### + +.. automodule:: odoo.addons.queue_job.jobrunner.runner + + +What is a channel? +------------------ + +.. autoclass:: odoo.addons.queue_job.jobrunner.channels.Channel + :noindex: + +How to configure Channels? +-------------------------- + +The ``ODOO_QUEUE_JOB_CHANNELS`` environment variable must be +set before starting Odoo in order to enable the job runner +and configure the capacity of the channels. + +The general syntax is ``channel(.subchannel)*(:capacity(:key(=value)?)*)?,...``. + +Intermediate subchannels which are not configured explicitly are autocreated +with an unlimited capacity (except the root channel which if not configured gets +a default capacity of 1). + +A delay in seconds between jobs can be set at the channel level with +the ``throttle`` key. + +Example ``ODOO_QUEUE_JOB_CHANNELS``: + +* ``root:4``: allow up to 4 concurrent jobs in the root channel. +* ``root:4,root.sub:2``: allow up to 4 concurrent jobs in the root channel and + up to 2 concurrent jobs in the channel named ``root.sub``. +* ``sub:2``: the same. +* ``root:4:throttle=2``: wait at least 2 seconds before starting the next job diff --git a/connector/doc/guides/migration_guide.rst b/connector/doc/guides/migration_guide.rst new file mode 100644 index 000000000..4b18c54f9 --- /dev/null +++ b/connector/doc/guides/migration_guide.rst @@ -0,0 +1,900 @@ +.. _migration-guide: + +######################################## +Migration Guide to the new Connector API +######################################## + +During the year 2017, the connector evolved greatly. +We can recognize three different aspect of the framework, they all have been +rewritten: + +* The Job Queue API (:ref:`api-queue`) +* The Event API (:ref:`api-event`) +* The ``ConnectorUnit`` API, which is the core of the composability + of the Connector. It has been replaced by a standalone addon + called ``component``. (:ref:`api-component`) + +The Connector has been splitted in different addons: + +* ``queue_job`` in https://github.com/OCA/queue +* ``component`` in the same repository +* ``component_event`` in the same repository +* ``connector`` uses the 3 addons and the parts specifics to the connectors + +This guide will show how to migrate from the old API to the new one. + +The previous API will stay until the migration to Odoo 11.0. + +.. contents:: Sections: + :local: + :backlinks: top + :depth: 2 + +************** +Migrating Jobs +************** + +Jobs are now more integrated within the Odoo API. They are no longer +standalone functions but are applied on methods of Models. Another change is +that they have been extracted into their own addon, so obviously the Python +paths change. + +Declaration of a job +==================== + +Before +------ + +.. code-block:: python + + from odoo.addons.connector.queue.job import job, related_action + from ..related_action import unwrap_binding, link + + # function at module-level + @job(default_channel='root.magento') + @related_action(action=link) + def import_record(session, model_name, backend_id, magento_id, force=False): + """ Import a record from Magento """ + # ... + + @job(default_channel='root.magento') + @related_action(action=unwrap_binding) + def export_record(session, model_name, binding_id, fields=None): + """ Import a record from Magento """ + # ... + + +After +----- + +.. code-block:: python + + from odoo.addons.queue_job.job import job, related_action + from odoo import api, models + + + class MagentoBinding(models.AbstractModel): + _name = 'magento.binding' + _inherit = 'external.binding' + _description = 'Magento Binding (abstract)' + + @job(default_channel='root.magento') + @related_action(action='related_action_magento_link') + @api.model + def import_record(self, backend, external_id, force=False): + """ Import a Magento record """ + backend.ensure_one() + # ... + + @job(default_channel='root.magento') + @related_action(action='related_action_unwrap_binding') + @api.multi + def export_record(self, fields=None): + """ Export a record on Magento """ + self.ensure_one() + # ... + + +Observations +------------ + +* The job is declared on the generic abstract binding model from which all + bindings inherit. This is not a requirement, but for this kind of job it is + the perfect fit. +* ``session``, ``model_name`` and ``binding_id`` are no longer required as they + are already known in ``self``. Jobs can be used as well on ``@api.multi`` and + ``@api.model``. +* Passing arguments as records is supported, in the new version of + ``import_record``, no need to browse on the backend if a record was passed +* The action of a related action is now the name of a method on the + ``queue.job`` model. +* If you need to share a job between several models, put them in an + AbstractModel and add an ``_inherit`` on the models. + +Links +----- + +* :meth:`odoo.addons.queue_job.job.job` +* :meth:`odoo.addons.queue_job.job.related_action` + + +Invocation of a job +=================== + +Before +------ + +.. code-block:: python + + from odoo.addons.connector.session import ConnectorSession + from .unit.export_synchronizer import export_record + + + class MyBinding(models.Model): + _name = 'my.binding' + _inherit = 'magento.binding' + + @api.multi + def button_trigger_export_sync(self): + session = ConnectorSession.from_env(self.env) + export_record(session, binding._name, self.id, fields=['name']) + + @api.multi + def button_trigger_export_async(self): + session = ConnectorSession.from_env(self.env) + export_record.delay(session, self._name, self.id, + fields=['name'], priority=12) + + +After +----- + +.. code-block:: python + + class MyBinding(models.Model): + _name = 'my.binding' + + @api.multi + def button_trigger_export_sync(self): + self.export_record(fields=['name']) + + @api.multi + def button_trigger_export_async(self): + self.with_delay(priority=12).export_record(fields=['name']) + +Observations +------------ + +* No more imports are needed for the invocation +* ``ConnectorSession`` is now dead +* Arguments for the job (such as ``priority``) are no longer mixed with the + arguments passed to the method +* When the job is called on a "browse" record, the job will be executed + on an instance of this record: + + .. code-block:: python + + >>> binding = self.env['my.binding'].browse(1) + >>> binding.button_trigger_export_async() + + In the execution of the job: + + .. code-block:: python + + @job + def export_record(self, fields=None): + print self + print fields + # => + # my.binding,1 + # ['name'] + +Links +----- + +* :meth:`odoo.addons.queue_job.job.job` +* :meth:`odoo.addons.queue_job.models.base.Base.with_delay` + +**************** +Migrating Events +**************** + +Events are now handled by the ``component_event`` addon. + +Triggering an event +=================== + +Before +------ + +First you had to create an :class:`~odoo.addons.connector.event.Event` instance: + +.. code-block:: python + + on_record_create = Event() + +And then import and trigger it, passing a lot of arguments to it: + +.. code-block:: python + + from odoo.addons.connector.event import on_record_create + + class Base(models.AbstractModel): + """ The base model, which is implicitly inherited by all models. """ + _inherit = 'base' + + @api.model + def create(self, vals): + record = super(Base, self).create(vals) + on_record_create.fire(self.env, self._name, record.id, vals) + return record + + +After +----- + +.. code-block:: python + + class Base(models.AbstractModel): + _inherit = 'base' + + @api.model + def create(self, vals): + record = super(Base, self).create(vals) + self._event('on_record_create').notify(record, fields=vals.keys()) + return record + +Observations +------------ + +* No more imports are needed for the invocation + Only the arguments you want to pass should be passed to + :meth:`odoo.addons.component_event.components.event.CollectedEvents.notify`. +* The name of the event must start with ``'on_'`` + +Links +----- + +* :mod:`odoo.addons.component_event.components.event` + + +Listening to an event +===================== + +Before +------ + +.. code-block:: python + + from odoo.addons.connector.event import on_record_create + + @on_record_create + def delay_export(env, model_name, record_id, vals): + if session.context.get('connector_no_export'): + return + fields = vals.keys() + export_record.delay(session, model_name, record_id, fields=fields) + + @on_something + def do_anything(env, model_name, record_id): + # ... + +After +----- + +.. code-block:: python + + from odoo.addons.component.core import Component + from odoo.addons.component_event import skip_if + + class MagentoListener(Component): + _name = 'magento.event.listener' + _inherit = 'base.connector.listener' + + @skip_if(lambda self, record, **kwargs: self.no_connector_export(record)) + def on_record_create(self, record, fields=None): + """ Called when a record is created """ + record.with_delay().export_record(fields=fields) + + def on_something(self, record): + # ... + +Observations +------------ + +* The listeners are now components +* The name of the method is the same than the one notified in the previous + section +* A listener Component might container several listener methods +* It must inherit from ``'base.event.listener'``, or one of its descendants. +* The check of the key ``connector_no_export`` in the context can + be replaced by the decorator :func:`odoo.addons.component_event.skip_if` + +Links +----- + +* :mod:`odoo.addons.component_event.components.event` + + +Listening to an event only for some Models +========================================== + +Before +------ + +.. code-block:: python + + from odoo.addons.connector.event import on_record_create + + @on_record_create(model_names=['magento.address', 'magento.res.partner']) + def delay_export(env, model_name, record_id, vals): + if session.context.get('connector_no_export'): + return + fields = vals.keys() + export_record.delay(session, model_name, record_id, fields=fields) + +After +----- + +.. code-block:: python + + from odoo.addons.component.core import Component + from odoo.addons.component_event import skip_if + + class MagentoListener(Component): + _name = 'magento.event.listener' + _inherit = 'base.event.listener' + _apply_on = ['magento.address', 'magento.res.partner'] + + @skip_if(lambda self, record, **kwargs: self.no_connector_export(record)) + def on_record_create(self, record, fields=None): + """ Called when a record is created """ + record.with_delay().export_record(fields=fields) + +Observations +------------ + +* Same than previous example but we added ``_apply_on`` on the Component. + +Links +----- + +* :mod:`odoo.addons.component_event.components.event` + + +******************** +Migrating Components +******************** + +Backends +======== + +Before +------ + +You could have several versions for a backend: + +.. code-block:: python + + magento = backend.Backend('magento') + """ Generic Magento Backend """ + + magento1700 = backend.Backend(parent=magento, version='1.7') + """ Magento Backend for version 1.7 """ + + magento1900 = backend.Backend(parent=magento, version='1.9') + """ Magento Backend for version 1.9 """ + + + +It was linked with a Backend model such as: + +.. code-block:: python + + class MagentoBackend(models.Model): + _name = 'magento.backend' + _description = 'Magento Backend' + _inherit = 'connector.backend' + + _backend_type = 'magento' + + @api.model + def select_versions(self): + """ Available versions in the backend. + Can be inherited to add custom versions. Using this method + to add a version from an ``_inherit`` does not constrain + to redefine the ``version`` field in the ``_inherit`` model. + """ + return [('1.7', '1.7+')] + + version = fields.Selection(selection='select_versions', required=True) + + + +After +----- + +All the :class:`backend.Backend` instances must be deleted. + +And the ``_backend_type`` must be removed from the Backend model. + +.. code-block:: python + + class MagentoBackend(models.Model): + _name = 'magento.backend' + _description = 'Magento Backend' + _inherit = 'connector.backend' + + @api.model + def select_versions(self): + """ Available versions in the backend. + Can be inherited to add custom versions. Using this method + to add a version from an ``_inherit`` does not constrain + to redefine the ``version`` field in the ``_inherit`` model. + """ + return [('1.7', '1.7+')] + + version = fields.Selection(selection='select_versions', required=True) + + +Observations +------------ + +* The version is now optional in the Backend Models. +* Backend Models are based on Component's Collections: + :class:`odoo.addons.component.models.collection.Collection` + +Links +----- + +* :ref:`api-component` +* :class:`odoo.addons.component.models.collection.Collection` + + +Inheritance +=========== + +Before +------ + +You could inherit a ``ConnectorUnit`` by creating a custom Backend +version and decorating your class with it + +.. code-block:: python + + magento_custom = backend.Backend(parent=magento1700, version='custom') + """ Custom Magento Backend """ + + +.. code-block:: python + + # base one + @magento + class MagentoPartnerAdapter(GenericAdapter): + # ... + + # other file... + + from .backend import magento_custom + + # custom one + @magento_custom + class MyPartnerAdapter(MagentoPartnerAdapter): + # ... + + def do_something(self): + # do it this way + +You could also replace an existing class, this is mentionned in `Replace or +unregister a component`_. + + +After +----- + +For an existing component: + +.. code-block:: python + + from odoo.addons.component.core import Component + + class MagentoPartnerAdapter(Component): + _name = 'magento.partner.adapter' + _inherit = 'magento.adapter' + + def do_something(self): + # do it this way + +You can extend it: + +.. code-block:: python + + from odoo.addons.component.core import Component + + class MyPartnerAdapter(Component): + _inherit = 'magento.partner.adapter' + + def do_something(self): + # do it this way + +Or create a new different component with the existing one as base: + +.. code-block:: python + + from odoo.addons.component.core import Component + + class MyPartnerAdapter(Component): + _name = 'my.magento.partner.adapter' + _inherit = 'magento.partner.adapter' + + def do_something(self): + # do it this way + + +Observations +------------ + +* The inheritance is similar to the Odoo's one (without ``_inherits``. +* All components have a Python inheritance on + :class:`~odoo.addons.component.core.AbstractComponent` or + :class:`~odoo.addons.component.core.Component` +* The names are global (as in Odoo), so you should prefix them with a namespace +* The name of the classes has no effect +* As in Odoo Models, a Component can ``_inherit`` from a list of Components +* All components implicitly inherits from a ``'base'`` component + +Links +----- + +* :ref:`api-component` +* :class:`odoo.addons.component.core.AbstractComponent` + + + +Entrypoint for working with components +====================================== + +Before +------ + +Previously, when you had to work with ``ConnectorUnit`` from a Model or from a job, +depending of the Odoo version you to: + +.. code-block:: python + + from odoo.addons.connector.connector import ConnectorEnvironment + + # ... + + backend_record = session.env['magento.backend'].browse(backend_id) + env = ConnectorEnvironment(backend_record, 'magento.res.partner') + importer = env.get_connector_unit(MagentoImporter) + importer.run(magento_id, force=force) + +Or: + +.. code-block:: python + + from odoo.addons.connector.connector import ConnectorEnvironment + from odoo.addons.connector.session import ConnectorSession + + #... + + backend_record = session.env['magento.backend'].browse(backend_id) + session = ConnectorSession.from_env(self.env) + env = ConnectorEnvironment(backend_record, session, 'magento.res.partner') + importer = env.get_connector_unit(MagentoImporter) + importer.run(external_id, force=force) + +Which was commonly abstracted in a helper function such as: + + +.. code-block:: python + + def get_environment(session, model_name, backend_id): + """ Create an environment to work with. """ + backend_record = session.env['magento.backend'].browse(backend_id) + env = ConnectorEnvironment(backend_record, session, 'magento.res.partner') + lang = backend_record.default_lang_id + lang_code = lang.code if lang else 'en_US' + if lang_code == session.context.get('lang'): + return env + else: + with env.session.change_context(lang=lang_code): + return env + +After +----- + +.. code-block:: python + + # ... + backend_record = self.env['magento.backend'].browse(backend_id) + with backend_record.work_on('magento.res.partner') as work: + importer = work.component(usage='record.importer') + importer.run(external_id, force=force) + +Observations +------------ + +* And when you are already in a Component, refer to `Find a component`_ + +Links +----- + +* :class:`~odoo.addons.component.core.WorkContext` + + +Find a component +================ + +Before +------ + +To find a ``ConnectorUnit``, you had to ask for given class or subclass: + +.. code-block:: python + + # our ConnectorUnit to find + @magento + class MagentoPartnerAdapter(GenericAdapter): + _model_name = ['magent.res.partner'] + + # other file... + + def run(self, record): + backend_adapter = self.unit_for(GenericAdapter) + +It was searched for the current model and the current backend. + +After +----- + +For an existing component: + +.. code-block:: python + + from odoo.addons.component.core import Component + + class MagentoPartnerAdapter(Component): + _name = 'magento.partner.adapter' + _inherit = 'magento.adapter' + + _usage = 'backend.adapter' + _collection = 'magento.backend' + _apply_on = ['res.partner'] + + # other file... + + def run(self, record): + backend_adapter = self.component(usage='backend.adapter') + + + +Observations +------------ + +* The model is compared with the ``_apply_on`` attribute +* The Backend is compared with the ``_collection`` attribute, it must + have the same name than the Backend Model. +* The ``_usage`` indicates what the purpose of the component is, and + allow to find the correct one for our task. It allow more dynamic + usages than the previous usage of a class. +* Usually, the ``_usage`` and the ``_collection`` will be ``_inherit`` 'ed from + a component (here from ``'magento.adapter``), so they won't need to be + repeated in all Components. +* A good idea is to have a base abstract Component for the Collection, then + an abstract Component for every usage:: + + class BaseMagentoConnectorComponent(AbstractComponent): + + _name = 'base.magento.connector' + _inherit = 'base.connector' + _collection = 'magento.backend' + + class MagentoBaseExporter(AbstractComponent): + """ Base exporter for Magento """ + + _name = 'magento.base.exporter' + _inherit = ['base.exporter', 'base.magento.connector'] + _usage = 'record.exporter' + + class MagentoImportMapper(AbstractComponent): + _name = 'magento.import.mapper' + _inherit = ['base.magento.connector', 'base.import.mapper'] + _usage = 'import.mapper' + + # ... + +* The main usages are: + * import.mapper + * export.mapper + * backend.adapter + * importer + * exporter + * binder + * event.listener +* But for the importer and exporter, I recommend to use more precise ones in + the connectors: record.importer, record.exporter, batch.importer, + batch.exporter +* You are allowed to be creative with the ``_usage``, it's the key that will + allow you to find the right one component you need. (e.g. on + ``stock.picking`` you need to 1. export the record, 2. export the tracking. + Then use ``record.exporter`` and ``tracking.exporter``). +* AbstractComponent will never be returned by a lookup + + +Links +----- + +* :ref:`api-component` +* :class:`odoo.addons.component.core.AbstractComponent` + + +Backend Versions +================ + +Before +------ + +You could have several versions for a backend: + +.. code-block:: python + + magento = backend.Backend('magento') + """ Generic Magento Backend """ + + magento1700 = backend.Backend(parent=magento, version='1.7') + """ Magento Backend for version 1.7 """ + + magento1900 = backend.Backend(parent=magento, version='1.9') + """ Magento Backend for version 1.9 """ + + +And use them for a class-level dynamic dispatch + +.. code-block:: python + + from odoo.addons.magentoerpconnect.backend import magento1700, magento1900 + + @magento1700 + class PartnerAdapter1700(GenericAdapter): + # ... + + def do_something(self): + # do it this way + + @magento1900 + class PartnerAdapter1900(GenericAdapter): + # ... + + def do_something(self): + # do it that way + + +After +----- + +This feature has been removed, it introduced a lot of complexity (notably +regarding inheritance) for few gain. The version is now optional on the +backends and the version dispatch, if needed, should be handled manually. + +In methods: + +.. code-block:: python + + from odoo.addons.component.core import Component + + class PartnerAdapter(Component): + # ... + + def do_something(self): + if self.backend_record.version == '1.7': + # do it this way + else: + # do it that way + +Or with a factory: + +.. code-block:: python + + from odoo.addons.component.core import Component + + class PartnerAdapterFactory(Component): + # ... + + def get_component(self, version): + if self.backend_record.version == '1.7': + return self.component(usage='backend.adapter.1.7') + else: + return self.component(usage='backend.adapter.1.9') + +Observations +------------ + +* None + +Links +----- + +* :ref:`api-component` + + +Replace or unregister a component +================================= + +Before +------ + +You could replace a ``ConnectorUnit`` with the ``replace`` argument passed to +the backend decorator: + +.. code-block:: python + + @magento(replacing=product.ProductImportMapper) + class ProductImportMapper(product.ProductImportMapper): + + +After +----- + +First point: this should hardly be needed now, as you can inherit a component +like Odoo Models. Still, if you need to totally replace a component by +another, let's say there is this component: + +.. code-block:: python + + from odoo.addons.component.core import Component + + class ProductImportMapper(Component): + _name = 'magento.product.import.mapper' + _inherit = 'magento.import.mapper' + + _apply_on = ['magento.product.product'] + # normally the following attrs are inherited from the _inherit + _usage = 'import.mapper' + _collection = 'magento.backend' + + +Then you can remove the usage of the component: it will never be used: + +.. code-block:: python + + from odoo.addons.component.core import Component + + class ProductImportMapper(Component): + _inherit = 'magento.product.import.mapper' + _usage = None + +And create your own, that will be picked up instead of the base one: + +.. code-block:: python + + from odoo.addons.component.core import Component + + class MyProductImportMapper(Component): + _name = 'my.magento.product.import.mapper' + _inherit = 'magento.import.mapper' + + _apply_on = ['magento.product.product'] + # normally the following attrs are inherited from the _inherit + _usage = 'import.mapper' + _collection = 'magento.backend' + + +Observations +------------ + +* None + +Links +----- + +* :ref:`api-component` + + +Various hints +============= + +* The components and the jobs know how to work with Model instances, + so prefer them over ids in parameters. diff --git a/connector/doc/index.rst b/connector/doc/index.rst new file mode 100644 index 000000000..56e4dc445 --- /dev/null +++ b/connector/doc/index.rst @@ -0,0 +1,126 @@ +.. Connectors documentation master file, created by + sphinx-quickstart on Mon Feb 4 11:35:44 2013. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +############## +Odoo Connector +############## + +Odoo Connector is a powerful framework to develop any kind of +bi-directional connector between `Odoo`_ (Open Source ERP) and any other +software or service. + +This Odoo add-on has a modular and generic core, with the +ability to be extended with additional modules for new features or +customizations. + +The development of Odoo Connector has been started by `Camptocamp`_ and is now +maintained by `Camptocamp`_, `Akretion`_, `Acsone`_ and several :ref:`contributors`. + +It got a major overhaul in 2017 (Odoo 10.0). A :ref:`migration-guide` is +available. + +*Subscribe to the* `project's mailing list (name: Connectors)`_ + +*Learn how to* :ref:`contribute` + +************* +Core Features +************* + +* **100% Open Source** (`LGPL version 3`_): the full `source code is available + on GitHub`_ +* Not only designed to connect Odoo with e-commerce backends, + rather it is **adaptable** to connect Odoo with any type of service. +* **Robust for high volumetries** and **easy to monitor** thanks to a :ref:`jobs-queue`. +* A flexible set of building blocks, it does not force to a certain + implementation but leaves the final choice to the + developer on how to use the proposed pieces. +* See a :ref:`code-overview` with examples of code + +.. _Odoo: https://www.odoo.com +.. _Camptocamp: https://www.camptocamp.com +.. _Akretion: http://www.akretion.com +.. _Acsone: https://www.acsone.eu +.. _`source code is available on GitHub`: https://github.com/OCA/connector +.. _`LGPL version 3`: https://www.gnu.org/licenses/lgpl-3.0.html +.. _`project's mailing list (name: Connectors)`: https://odoo-community.org/groups + +***************** +Developer's guide +***************** + +.. toctree:: + :maxdepth: 2 + + guides/migration_guide.rst + guides/code_overview.rst + guides/concepts.rst + guides/bootstrap_connector.rst + guides/jobrunner.rst + +API Reference +============= + +.. toctree:: + :maxdepth: 1 + + api/api_components.rst + api/api_backend.rst + api/api_event.rst + api/api_queue.rst + api/api_exception.rst + api/api_channels.rst + +******* +Project +******* + +.. toctree:: + :maxdepth: 1 + + project/contribute + project/contributors + project/license + project/roadmap + +********************************* +Connectors based on the framework +********************************* + +* `Magento Connector `_ +* `Prestashop Connector `_ +* `Search Engine Connector `_ +* `CMIS `_ +* `Odoo Asynchronous import module `_ +* `Salesforce Connector `_ +* `JIRA Connector `_ +* `Google Spreadsheet Connector `_ +* `Connector Exchange `_ +* `Infor Connector `_ +* `Voicent Connector `_ +* Develop easily and rapidly your own connector based on this powerful + framework and list your project on this page! Examples: + + * E-Commerce: Odoo OsCommerce connector, Odoo Drupal Commerce connector, Odoo Spree connector, Odoo Ebay connector, Odoo Amazon connector… + * CMS: Odoo Wordpress connector… + * CRM: Odoo SugarCRM connector, Odoo Zabbix connector… + * Project Management: Odoo Redmine connector… + * Ticketing: Odoo Request Tracker connector, Odoo GLPI connector… + + +***** +Talks +***** + +* `A jobs queue for processing tasks asynchronously. Leonardo Pistone & Guewen Baconnier (2015) `_ +* `E-commerce: the new Magento - OpenERP Connector: a generic connector to any apps. Luc Maurer & Guewen Baconnier, Camptocamp (2013) `_ + +****************** +Indices and tables +****************** + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/connector/doc/locale/fr/LC_MESSAGES/api.po b/connector/doc/locale/fr/LC_MESSAGES/api.po new file mode 100644 index 000000000..82282dfef --- /dev/null +++ b/connector/doc/locale/fr/LC_MESSAGES/api.po @@ -0,0 +1,3407 @@ +# +msgid "" +msgstr "" +"Project-Id-Version: Connector\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-04-15 22:28+0300\n" +"PO-Revision-Date: 2015-04-17 13:54+0200\n" +"Last-Translator: Christophe Combelles \n" +"Language-Team: fr \n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 1.6.10\n" + +#. module: connector +#: ../../api/api_backend.rst:2 +msgid "Backend" +msgstr "Backend" + +#. module: connector +#: ../../api/api_backend.rst:4 +msgid "" +"A backend for a version (for instance Magento 1.7), is represented by an " +"instance of the :py:class:`~connector.backend.Backend` class." +msgstr "" +"Le backend pour une version (par exemple Magento 1.7) est représenté par une" +" instance de la classe :py:class:`~connector.backend.Backend`." + +#. module: connector +#: ../../api/api_backend.rst:7 +msgid "" +"Each connector will also create a ``connector.backend`` which allows the " +"users to register their backends. For instance, the Magento connector has " +"``magento.backend`` (``_inherit`` " +":py:class:`connector.models.backend_model.connector_backend`). This model contains" +" a ``version`` field which should have the same list of versions (with the " +"exact same name) than the instances of " +":py:class:`~connector.backend.Backend`." +msgstr "" +"Chaque connecteur va aussi créer un ``connector.backend`` qui permet aux " +"utilisateurs d'inscrire leurs backends. Par exemple le connecteur Magento a " +"un ``magento.backend`` (``_inherit`` " +":py:class:`connector.models.backend_model.connector_backend`). Ce modèle contient " +"un champ ``version`` qui doit avoir la même lists de versions (avec " +"exactement le même nom) que les instances de " +":py:class:`~connector.backend.Backend`." + +#. module: connector +#: ../../api/api_backend.rst:14 +msgid "Example with the Magento Connector::" +msgstr "Exemple avec le connecteur Magento ::" + +#. module: connector +#: ../../api/api_backend.rst:54 +msgid "" +"In the code above, '1.7' is the matching key between the " +":py:class:`~connector.backend.Backend` instance (``magento1700``) and the " +"``magento_backend`` record." +msgstr "" +"Dans le code ci-dessus, '1.7' est la clé de correspondance entre l'instance " +"de :py:class:`~connector.backend.Backend` (``magento1700``) et " +"l'enregistrement ``magento_backend``." + +#. module: connector +#: ../../../backend.pydocstring of connector.backend.Backend:1 +#: ../../../connector.pydocstring of +#: connector.connector.ConnectorEnvironment:1 ../../../connector.pydocstring +#: of connector.connector.ConnectorUnit:1 ../../../event.pydocstring of +#: connector.event.Event:1 ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.MapRecord:1 ../../../queue/job.pydocstring of +#: connector.queue.job.Job:1 ../../../queue/job.pydocstring of +#: connector.queue.job.JobStorage:1 ../../../queue/queue.pydocstring of +#: connector.queue.queue.JobsQueue:1 ../../../session.pydocstring of +#: connector.session.ConnectorSession:1 ../../../session.pydocstring of +#: connector.session.ConnectorSessionHandler:1 +msgid "Bases: :class:`object`" +msgstr "Bases : :class:`object`" + +#. module: connector +#: ../../../backend.pydocstring of connector.backend.Backend:1 +msgid "" +"A backend represents a system to interact with, like Magento, Prestashop, " +"Redmine, ..." +msgstr "" +"Un backend représente un système avec lequel interagir, comme Magento, " +"Prestashop, Redmine, ..." + +#. module: connector +#: ../../../backend.pydocstring of connector.backend.Backend:4 +msgid "It owns 3 properties:" +msgstr "Il possède trois propriétés :" + +#. module: connector +#: ../../../backend.pydocstring of connector.backend.Backend:8 +msgid "Name of the service, for instance 'magento'" +msgstr "Le nom du service, par exemple 'magento'" + +#. module: connector +#: ../../../backend.pydocstring of connector.backend.Backend:12 +msgid "The version of the service. For instance: '1.7'" +msgstr "La version du service. Par exemple '1.7'" + +#. module: connector +#: ../../../backend.pydocstring of connector.backend.Backend:16 +msgid "" +"A parent backend. When no :py:class:`~connector.connector.ConnectorUnit` is " +"found for a backend, it will search it in the `parent`." +msgstr "" +"Un backend parent. Lorsqu'aucune classe " +":py:class:`~connector.connector.ConnectorUnit` n'est trouvée pour un " +"backend, elle est cherchée dans le `parent`." + +#. module: connector +#: ../../../backend.pydocstring of connector.backend.Backend:20 +msgid "" +"The Backends structure is a key part of the framework, but is rather simple." +msgstr "" +"La structure des Backends est la partie clé du framework, mais elle est " +"plutôt simple." + +#. module: connector +#: ../../../backend.pydocstring of connector.backend.Backend:23 +msgid "" +"A ``Backend`` instance holds a registry of " +":py:class:`~connector.connector.ConnectorUnit` classes" +msgstr "" +"Une instance de ``Backend`` contient un registre de classes " +":py:class:`~connector.connector.ConnectorUnit`" + +#. module: connector +#: ../../../backend.pydocstring of connector.backend.Backend:25 +msgid "" +"It can return the appropriate :py:class:`~connector.connector.ConnectorUnit`" +" to use for a task" +msgstr "" +"Il peut renvoyer la classe :py:class:`~connector.connector.ConnectorUnit` à " +"utiliser pour une tâche" + +#. module: connector +#: ../../../backend.pydocstring of connector.backend.Backend:27 +msgid "" +"If no :py:class:`~connector.connector.ConnectorUnit` is registered for a " +"task, it will ask it to its direct parent (and so on)" +msgstr "" +"Si aucune :py:class:`~connector.connector.ConnectorUnit` n'est inscrite pour" +" une tâche, le parent direct est interrogé (et ainsi de suite)" + +#. module: connector +#: ../../../backend.pydocstring of connector.backend.Backend:31 +msgid "" +"The Backends support 2 different extension mechanisms. One is more vertical " +"- across the versions - and the other would be more horizontal as it allows " +"to modify the behavior for 1 version of backend." +msgstr "" +"Les Backends ont deux mécanismes différents d'extension. L'un est plus " +"vertical (entre plusieurs versions) et l'autre est plus horizontal car il " +"permet de modifier le comportement pour une version donnée du backend." + +#. module: connector +#: ../../../backend.pydocstring of connector.backend.Backend:35 +msgid "" +"For the sake of the example, let's say we have theses backend versions::" +msgstr "" +"Pour l'exemple, disons que nous avons les versions suivantes de backend ::" + +#. module: connector +#: ../../../backend.pydocstring of connector.backend.Backend:45 +msgid "And here is the way they are declared in Python::" +msgstr "Et voici la façon dont elles sont déclarées en Python ::" + +#. module: connector +#: ../../../backend.pydocstring of connector.backend.Backend:53 +msgid "" +"In the graph above, ```` will hold all the classes shared between " +"all the versions. Each Magento version (````, ````) will use the classes defined on ````, excepted if they " +"registered their own ones instead. That's the same for ```` but this one contains customizations which are specific to an " +"instance (typically you want specific mappings for one instance)." +msgstr "" +"Dans le graphe ci-dessus, ```` va contenir toutes les classes " +"partagées entre toutes les versions. Chaque version de Magento (````, ````) va utiliser les classes définies sur " +"````, sauf si elles ont inscrit leur propres classes. C'est la même" +" chose pour ```` mais celui-ci contient des " +"personnalisations qui sont spécifiques à une instance (typiquement pour " +"mettre en place des mappeurs spécifiques à une instance)." + +#. module: connector +#: ../../../backend.pydocstring of connector.backend.Backend:60 +msgid "" +"Here is how you would register classes on ```` and another on " +"````::" +msgstr "" +"Voici comment inscrire des classes sur ```` et une autre sur " +"```` ::" + +#. module: connector +#: ../../../backend.pydocstring of connector.backend.Backend:75 +msgid "" +"Here, the :py:meth:`~get_class` called on ``magento1700`` would return::" +msgstr "" +"Ici, la méthode :py:meth:`~get_class` appelé sur ``magento1700`` renverrait " +"::" + +#. module: connector +#: ../../../backend.pydocstring of connector.backend.Backend:82 +msgid "" +"This is the vertical extension mechanism, it says that each child version is" +" able to extend or replace the behavior of its parent." +msgstr "" +"C'est le mécanisme d'extension verticale, il dit que chaque version fille " +"est capable d'étendre ou remplacer le comportement de son parent." + +#. module: connector +#: ../../../backend.pydocstring of connector.backend.Backend:85 +msgid "when using the framework, you won't need to call" +msgstr "en utilisant le framework, vous n'aurez pas besoin d'appeler" + +#. module: connector +#: ../../../backend.pydocstring of connector.backend.Backend:86 +msgid "" +":py:meth:`~get_class`, usually, you will call " +":py:meth:`connector.connector.ConnectorEnvironment.get_connector_unit`." +msgstr "" +":py:meth:`~get_class`, habituellement vous appellerez " +":py:meth:`connector.connector.ConnectorEnvironment.get_connector_unit`." + +#. module: connector +#: ../../../backend.pydocstring of connector.backend.Backend:89 +msgid "" +"The vertical extension is the one you will probably use the most, because " +"most of the things you will change concern your custom adaptations or " +"different behaviors between the versions of the backend." +msgstr "" +"L'extension verticale est celle que vous utiliserez probablement le plus, " +"parce que la plupart des choses que vous modifierez concerne vos " +"applications personnalisées ou des comportements différents selon les " +"versions du backend." + +#. module: connector +#: ../../../backend.pydocstring of connector.backend.Backend:93 +msgid "" +"However, some time, we need to change the behavior of a connector, by " +"installing an addon. For example, say that we already have an " +"``ImportMapper`` for the products in the Magento Connector. We create a - " +"generic - addon to handle the catalog in a more advanced manner. We redefine" +" an ``AdvancedImportMapper``, which should be used when the addon is " +"installed. This is the horizontal extension mechanism." +msgstr "" +"Cependant il peut arriver que nous ayons besoin de changer le comportement " +"d'un connecteur, en installant un module. Par exemple, imaginons que nous " +"ayons déjà un ``ImportMapper`` pour les articles dans le Connecteur Magento." +" Nous créons un module (générique) pour gérer le catalogue d'une manière " +"plus avancée. Nous redéfinissons un ``AdvancedImportMapper`` qui devrait " +"être utilisé quand le module est installé. Ceci est le mécanisme d'extension" +" horizontal." + +#. module: connector +#: ../../../backend.pydocstring of connector.backend.Backend:100 +msgid "" +"Replace a :py:class:`~connector.connector.ConnectorUnit` by another one in a" +" backend::" +msgstr "" +"Remplace une clase :py:class:`~connector.connector.ConnectorUnit` par une " +"autre dans le backend ::" + +#. module: connector +#: ../../../backend.pydocstring of connector.backend.Backend:107 +msgid "" +"The horizontal extension should be used sparingly and cautiously since as " +"soon as 2 addons want to replace the same class, you'll have a conflict " +"(which would need to create a third addon to glue them, ``replacing`` can " +"take a tuple of classes to replace and this is exponential). This mechanism " +"should be used only in some well placed circumstances for generic addons." +msgstr "" +"L'extension horizontale devrait être utilisée de manière très occasionnelle " +"et précautionneuse, car dès que deux modules voudront remplacer la même " +"classe il y aura un conflit (qui nécessiterait de créer un troisième module " +"pour lier les deux, le remplacement pouvant prendre un tuple de classes à " +"remplacer et ceci étant exponentiel). Ce mécanisme ne devrait être utilisé " +"que dans certains circonstances bien précises pour des modules génériques." + +#. module: connector +#: ../../../backend.pydocstring of connector.backend.Backend.get_class:1 +msgid "Find a matching subclass of ``base_class`` in the registered classes." +msgstr "" +"Trouve une sous-classe correspondante à ``base_class`` dans les classes " +"inscrites." + +#. module: connector +#: ../../../backend.pydocstring of connector.backend.Backend.get_class:4 +msgid "class (and its subclass) to search in the registry" +msgstr "Classe (et sous-classe) à rechercher dans le registre" + +#. module: connector +#: ../../../backend.pydocstring of connector.backend.Backend.get_class:6 +#: ../../../connector.pydocstring of connector.connector.ConnectorUnit.match:4 +#: ../../../event.pydocstring of connector.event.Event.fire:7 +msgid "current session" +msgstr "session en cours" + +#. module: connector +#: ../../../backend.pydocstring of connector.backend.Backend.match:1 +msgid "Used to find the backend for a service and a version" +msgstr "Utilisé pour trouver le backend pour un service et une version" + +#. module: connector +#: ../../../backend.pydocstring of connector.backend.Backend.register_class:1 +msgid "Register a class in the backend." +msgstr "Inscrit une classe dans le backend" + +#. module: connector +#: ../../../backend.pydocstring of connector.backend.Backend.register_class:3 +msgid "the ConnectorUnit class class to register" +msgstr "la classe ConnectorUnit à inscrire" + +#. module: connector +#: ../../../backend.pydocstring of connector.backend.Backend.register_class:5 +msgid "optional, the ConnectorUnit class to replace" +msgstr "optionnel, la classe ConnectorUnit à remplacer" + +#. module: connector +#: ../../api/api_backend.rst:64 +msgid "Backend Models" +msgstr "Modèles du backend" + +#. module: connector +#: ../../../backend_model.pydocstring of +#: connector.models.backend_model.ConnectorBackend:1 +#: ../../../backend_model.pydocstring of +#: connector.models.backend_model.ExternalBinding:1 +msgid "Bases: :class:`odoo.models.AbstractModel`" +msgstr "Bases : :class:`odoo.models.AbstractModel`" + +#. module: connector +#: ../../../backend_model.pydocstring of +#: connector.models.backend_model.ConnectorBackend:1 +msgid "An instance of an external backend to synchronize with." +msgstr "Une instance d'un backend externe auquel se synchroniser" + +#. module: connector +#: ../../../backend_model.pydocstring of +#: connector.models.backend_model.ConnectorBackend:3 +msgid "" +"The backends have to ``_inherit`` this model in the connectors modules." +msgstr "" +"Les backends doivent ``_inherit`` ce modèle dans les modules des " +"connecteurs." + +#. module: connector +#: ../../../backend_model.pydocstring of +#: connector.models.backend_model.ConnectorBackend.get_backend:1 +msgid "" +"For a record of backend, returns the appropriate instance of " +":py:class:`~connector.backend.Backend`." +msgstr "" +"Pour un enregistrement d'un backend, renvoie l'instance appropriée de " +":py:class:`~connector.backend.Backend`." + +#. module: connector +#: ../../../backend_model.pydocstring of +#: connector.models.backend_model.ConnectorBackend.name:1 +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueJob.func_string:1 +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueJob.model_name:1 +#: ../../../queue/model.pydocstring of connector.queue.model.QueueJob.name:1 +#: ../../../queue/model.pydocstring of connector.queue.model.QueueJob.uuid:1 +#: ../../../queue/model.pydocstring of connector.queue.model.QueueWorker.pid:1 +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueWorker.uuid:1 +msgid "" +"Basic string field, can be length-limited, usually displayed as a single-" +"line string in clients" +msgstr "" +"Champ chaîne de caractère basique, peut être limité en longeur, " +"habituellement affiché comme ligne unique dans les clients" + +#. module: connector +#: ../../../backend_model.pydocstring of +#: connector.models.backend_model.ConnectorBackend.name:4 +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueJob.func_string:4 +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueJob.model_name:4 +#: ../../../queue/model.pydocstring of connector.queue.model.QueueJob.name:4 +#: ../../../queue/model.pydocstring of connector.queue.model.QueueJob.uuid:4 +#: ../../../queue/model.pydocstring of connector.queue.model.QueueWorker.pid:4 +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueWorker.uuid:4 +msgid "the maximum size of values stored for that field" +msgstr "la taille maximum des valeurs stockées dans ce champ" + +#. module: connector +#: ../../../backend_model.pydocstring of +#: connector.models.backend_model.ConnectorBackend.name:5 +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueJob.func_string:5 +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueJob.model_name:5 +#: ../../../queue/model.pydocstring of connector.queue.model.QueueJob.name:5 +#: ../../../queue/model.pydocstring of connector.queue.model.QueueJob.uuid:5 +#: ../../../queue/model.pydocstring of connector.queue.model.QueueWorker.pid:5 +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueWorker.uuid:5 +msgid "whether the values of this field can be translated" +msgstr "si les valeurs de ce champ peuvent être traduites" + +#. module: connector +#: ../../../backend_model.pydocstring of +#: connector.models.backend_model.ConnectorBackend.version:1 +#: ../../../queue/model.pydocstring of connector.queue.model.QueueJob.state:1 +msgid "" +"specifies the possible values for this field. It is given as either a list " +"of pairs (`value`, `string`), or a model method, or a method name." +msgstr "" +"précise les valeurs possible de ce champs. C'est donné soit comme liste de " +"paires (`valeur`, `chaîne`), soit comme méthode de modèle, soit comme nom de" +" méthode." + +#. module: connector +#: ../../../backend_model.pydocstring of +#: connector.models.backend_model.ConnectorBackend.version:4 +#: ../../../queue/model.pydocstring of connector.queue.model.QueueJob.state:4 +msgid "" +"provides an extension of the selection in the case of an overridden field. " +"It is a list of pairs (`value`, `string`)." +msgstr "" +"fournit une extension de la sélection dans le cas d'un champ surchargé. " +"C'est une liste de paires (`value`, `string`)." + +#. module: connector +#: ../../../backend_model.pydocstring of +#: connector.models.backend_model.ConnectorBackend.version:7 +#: ../../../queue/model.pydocstring of connector.queue.model.QueueJob.state:7 +msgid "" +"The attribute `selection` is mandatory except in the case of :ref:`related " +"fields ` or :ref:`field extensions `." +msgstr "" +"L'attribut `selection` est obligatoire sauf dans le cas de :ref:`related " +"fields ` ou :ref:`field extensions `." + +#. module: connector +#: ../../../backend_model.pydocstring of +#: connector.models.backend_model.ExternalBinding:1 +msgid "An abstract model for bindings to external records." +msgstr "Un modèle abstrait pour une liaison à des enregistrements externes" + +#. module: connector +#: ../../../backend_model.pydocstring of +#: connector.models.backend_model.ExternalBinding:3 +msgid "" +"An external binding is a binding between a backend and Odoo. For " +"example, for a partner, it could be ``magento.res.partner`` or for a " +"product, ``magento.product``." +msgstr "" +"Un binding externe est une liaison entre un backend et Odoo. Par exemple," +" pour un `partner`, cela peut être ``magento.res.partner`` ou pour un " +"article, ``magento.product``." + +#. module: connector +#: ../../../backend_model.pydocstring of +#: connector.models.backend_model.ExternalBinding:7 +msgid "" +"The final model, will be an ``_inherits`` of the Odoo model and will " +"``_inherit`` this model." +msgstr "" +"Le modèle final sera un ``_inherits`` du modèle Odoo et va ``_inherit`` " +"ce modèle." + +#. module: connector +#: ../../../backend_model.pydocstring of +#: connector.models.backend_model.ExternalBinding:10 +msgid "" +"It will have a relation to the record (via ``_inherits``) and to the " +"concrete backend model (``magento.backend`` for instance)." +msgstr "" +"Il aura une relation vers l'enregistrement (via ``_inherits``) et vers le " +"modèle backend concret (par exemple ``magento.backend``)." + +#. module: connector +#: ../../../backend_model.pydocstring of +#: connector.models.backend_model.ExternalBinding:13 +msgid "" +"It will also contains all the data relative to the backend for the record." +msgstr "" +"Il contiendra également toutes les données relatives aux backend pour " +"l'enregistrement." + +#. module: connector +#: ../../../backend_model.pydocstring of +#: connector.models.backend_model.ExternalBinding:16 +msgid "It needs to implements at least these fields:" +msgstr "Il nécessite d'implémenter au moins ces champs :" + +#. module: connector +#: ../../../backend_model.pydocstring of +#: connector.models.backend_model.ExternalBinding:18 +msgid "odoo_id" +msgstr "odoo_id" + +#. module: connector +#: ../../../backend_model.pydocstring of +#: connector.models.backend_model.ExternalBinding:20 +msgid "The many2one to the record it links (used by ``_inherits``)." +msgstr "Le many2one vers l'enregistrement lié (utilisé par ``_inherits``)." + +#. module: connector +#: ../../../backend_model.pydocstring of +#: connector.models.backend_model.ExternalBinding:22 +msgid "backend_id" +msgstr "backend_id" + +#. module: connector +#: ../../../backend_model.pydocstring of +#: connector.models.backend_model.ExternalBinding:24 +msgid "The many2one to the backend (for instance ``magento.backend``)." +msgstr "Le many2one vers le backend (par exemple ``magento.backend``)." + +#. module: connector +#: ../../../backend_model.pydocstring of +#: connector.models.backend_model.ExternalBinding:26 +msgid "magento_id or prestashop_id or ..." +msgstr "magento_id ou prestashop_id ou ..." + +#. module: connector +#: ../../../backend_model.pydocstring of +#: connector.models.backend_model.ExternalBinding:28 +msgid "The ID on the backend." +msgstr "L'ID sur le backend." + +#. module: connector +#: ../../../backend_model.pydocstring of +#: connector.models.backend_model.ExternalBinding:30 +msgid "sync_date" +msgstr "sync_date" + +#. module: connector +#: ../../../backend_model.pydocstring of +#: connector.models.backend_model.ExternalBinding:32 +msgid "Last date of synchronization" +msgstr "Dernière date de synchronisation" + +#. module: connector +#: ../../../backend_model.pydocstring of +#: connector.models.backend_model.ExternalBinding:35 +msgid "" +"The definition of the relations in ``_columns`` is to be done in the " +"concrete classes because the relations themselves do not exist in this " +"addon." +msgstr "" +"La définition des relations dans ``_columns`` doit être faite dans les " +"classes concrètes, parce que les relations elle-mêmes n'existent pas dans ce" +" module." + +#. module: connector +#: ../../../backend_model.pydocstring of +#: connector.models.backend_model.ExternalBinding:39 +msgid "" +"For example, for a ``res.partner.category`` from Magento, I would have (this" +" is a consolidation of all the columns from the abstract models, in " +"``magentoerpconnect`` you would not find that)::" +msgstr "" +"Par exemple, pour un ``res.partner.category`` depuis Magento, J'aurais (ceci" +" est une consolidation de toutes les colonnes des modèles abstraits. Dans " +"``magentoerpconnect`` vous ne trouveriez pas ça) ::" + +#. module: connector +#: ../../api/api_backend_adapter.rst:2 +msgid "Backend Adapter" +msgstr "Adaptateur de backend" + +#. module: connector +#: ../../../unit/backend_adapter.pydocstring of +#: connector.unit.backend_adapter.BackendAdapter:1 +#: ../../../connector.pydocstring of connector.connector.Binder:1 +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.MapChild:1 +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.Mapper:1 +#: ../../../unit/synchronizer.pydocstring of +#: connector.unit.synchronizer.Synchronizer:1 +msgid "Bases: :class:`connector.connector.ConnectorUnit`" +msgstr "Bases : :class:`connector.connector.ConnectorUnit`" + +#. module: connector +#: ../../../unit/backend_adapter.pydocstring of +#: connector.unit.backend_adapter.BackendAdapter:1 +msgid "Base Backend Adapter for the connectors" +msgstr "Adaptateur de backend de base pour les connecteurs" + +#. module: connector +#: ../../../unit/backend_adapter.pydocstring of +#: connector.unit.backend_adapter.CRUDAdapter:1 +msgid "Bases: :class:`connector.unit.backend_adapter.BackendAdapter`" +msgstr "Bases : :class:`connector.unit.backend_adapter.BackendAdapter`" + +#. module: connector +#: ../../../unit/backend_adapter.pydocstring of +#: connector.unit.backend_adapter.CRUDAdapter:1 +msgid "" +"Base External Adapter specialized in the handling of records on external " +"systems." +msgstr "" +"Adaptateur externe de base spécialisé dans la gestion des enregistrements " +"des systèmes externes." + +#. module: connector +#: ../../../unit/backend_adapter.pydocstring of +#: connector.unit.backend_adapter.CRUDAdapter:4 +msgid "Subclasses can implement their own implementation for the methods." +msgstr "Sous-classes qui ont leur propre implémentation pour les méthodes." + +#. module: connector +#: ../../../unit/backend_adapter.pydocstring of +#: connector.unit.backend_adapter.CRUDAdapter.create:1 +msgid "Create a record on the external system" +msgstr "Crée un enregistrement dans le système externe" + +#. module: connector +#: ../../../unit/backend_adapter.pydocstring of +#: connector.unit.backend_adapter.CRUDAdapter.delete:1 +msgid "Delete a record on the external system" +msgstr "Supprime un enregistrement sur le système externe" + +#. module: connector +#: ../../../unit/backend_adapter.pydocstring of +#: connector.unit.backend_adapter.CRUDAdapter.read:1 +msgid "Returns the information of a record" +msgstr "Renvoie des informations sur l'enregistrement" + +#. module: connector +#: ../../../unit/backend_adapter.pydocstring of +#: connector.unit.backend_adapter.CRUDAdapter.search:1 +msgid "Search records according to some criterias and returns a list of ids" +msgstr "" +"Recherche des enregistrements correspondant à certains critères et renvoie " +"une liste d'IDs" + +#. module: connector +#: ../../../unit/backend_adapter.pydocstring of +#: connector.unit.backend_adapter.CRUDAdapter.search_read:1 +msgid "" +"Search records according to some criterias and returns their information" +msgstr "" +"Recherche des enregistrements correspondant à certains critères et renvoie " +"leurs données" + +#. module: connector +#: ../../../unit/backend_adapter.pydocstring of +#: connector.unit.backend_adapter.CRUDAdapter.write:1 +msgid "Update records on the external system" +msgstr "Met à jour les enregistrements sur le système externe" + +#. module: connector +#: ../../api/api_binder.rst:2 +msgid "Binder" +msgstr "Binder (Liant)" + +#. module: connector +#: ../../api/api_connector.rst:2 +msgid "Connector" +msgstr "Connecteur" + +#. module: connector +#: ../../../connector.pydocstring of connector.connector.Binder:1 +msgid "" +"For one record of a model, capable to find an external or internal id, or " +"create the binding (link) between them" +msgstr "" +"Pour un enregistrement d'un modèle, capable de trouver un ID externe ou " +"interne, ou crée la liaison entre eux" + +#. module: connector +#: ../../../connector.pydocstring of connector.connector.Binder:4 +msgid "The Binder should be implemented in the connectors." +msgstr "Le Binder devrait être implémenté dans les connecteurs." + +#. module: connector +#: ../../../connector.pydocstring of connector.connector.Binder.bind:1 +msgid "Create the link between an external ID and an Odoo ID" +msgstr "Crée le lien entre un ID externe et un ID Odoo" + +#. module: connector +#: ../../../connector.pydocstring of connector.connector.Binder.bind:3 +msgid "external id to bind" +msgstr "ID externe à lier" + +#. module: connector +#: ../../../connector.pydocstring of connector.connector.Binder.bind:4 +msgid "Odoo ID to bind" +msgstr "ID Odoo à lier" + +#. module: connector +#: ../../../connector.pydocstring of connector.connector.Binder.to_backend:1 +msgid "" +"Give the external ID for an Odoo binding ID (ID in a model magento.*)" +msgstr "" +"Donne l'ID externe pour un ID de liaison Odoo (ID dans un modèle " +"magento.*)" + +#. module: connector +#: ../../../connector.pydocstring of connector.connector.Binder.to_backend:4 +msgid "Odoo binding ID for which we want the backend id" +msgstr "ID de liaison Odoo pour lequel on veut l'ID du backend" + +#. module: connector +#: ../../../connector.pydocstring of connector.connector.Binder.to_backend:5 +msgid "" +"if False, binding_id is the ID of the binding, if True, binding_id is the ID" +" of the normal record, the method will search the corresponding binding and " +"returns the backend id of the binding" +msgstr "" +"si Faux, binding_id est l'ID de la liaison, si Vrai, binding_id est l'ID de " +"l'enregistrement normal, la méthode va chercher la liaison correspondante et" +" renvoyer l'ID de backend de la liaison." + +#. module: connector +#: ../../../connector.pydocstring of connector.connector.Binder.to_backend:9 +msgid "external ID of the record" +msgstr "ID externe de l'enregistrement" + +#. module: connector +#: ../../../connector.pydocstring of connector.connector.Binder.to_odoo:1 +msgid "Give the Odoo ID for an external ID" +msgstr "Donne l'ID Odoo pour un ID externe" + +#. module: connector +#: ../../../connector.pydocstring of connector.connector.Binder.to_odoo:3 +msgid "external ID for which we want the Odoo ID" +msgstr "ID externe pour lequel on veut l'ID Odoo" + +#. module: connector +#: ../../../connector.pydocstring of connector.connector.Binder.to_odoo:5 +msgid "if True, returns the odoo_id else return the id of the binding" +msgstr "si Vrai, renvoie l'odoo_id, sinon renvoie l'ID de la liaison" + +#. module: connector +#: ../../../connector.pydocstring of connector.connector.Binder.to_odoo:7 +msgid "if True, returns a recordset" +msgstr "si Vrai, renvoie un `recordset`" + +#. module: connector +#: ../../../connector.pydocstring of connector.connector.Binder.to_odoo:8 +msgid "" +"a record ID, depending on the value of unwrap, or None if the external_id is" +" not mapped" +msgstr "" +"un ID d'enregistrement, en fonction de la valeur à déballer, ou None si " +"l'external_id n'est pas mappé" + +#. module: connector +#: ../../../connector.pydocstring of +#: connector.connector.Binder.unwrap_binding:1 +msgid "For a binding record, gives the normal record." +msgstr "Pour un enregistrement de liaison, donne l'enregistrement normal" + +#. module: connector +#: ../../../connector.pydocstring of +#: connector.connector.Binder.unwrap_binding:3 +msgid "" +"Example: when called with a ``magento.product.product`` id, it will return " +"the corresponding ``product.product`` id." +msgstr "" +"Exemple : si appelé avec un ID de ``magento.product.product``, il va " +"renvoyer l'ID correspondant du ``product.product``." + +#. module: connector +#: ../../../connector.pydocstring of +#: connector.connector.Binder.unwrap_binding:6 +msgid "when True, returns a browse_record instance rather than an ID" +msgstr "si Vrai, renvoie une instance de `browse_record` à la place d'un ID" + +#. module: connector +#: ../../../connector.pydocstring of connector.connector.Binder.unwrap_model:1 +msgid "For a binding model, gives the normal model." +msgstr "Pour un modèle de liaison, donne le modèle normal." + +#. module: connector +#: ../../../connector.pydocstring of connector.connector.Binder.unwrap_model:3 +msgid "" +"Example: when called on a binder for ``magento.product.product``, it will " +"return ``product.product``." +msgstr "" +"Exemple : si appelé sur une binder pour ``magento.product.product``, il va " +"renvoyer ``product.product``." + +#. module: connector +#: ../../../connector.pydocstring of +#: connector.connector.ConnectorEnvironment:1 +msgid "Environment used by the different units for the synchronization." +msgstr "" +"Environnement utilisé par les différentes unités pour la synchronisation." + +#. module: connector +#: ../../../connector.pydocstring of +#: connector.connector.ConnectorEnvironment:5 +msgid "" +"Current backend we are working with. Obtained with " +"``backend_record.get_backend()``." +msgstr "" +"Backend en cours sur lesquels on travaille. Obtenu avec " +"``backend_record.get_backend()``." + +#. module: connector +#: ../../../connector.pydocstring of +#: connector.connector.ConnectorEnvironment:8 +msgid "Instance of: :py:class:`connector.backend.Backend`" +msgstr "Instance de : :py:class:`connector.backend.Backend`" + +#. module: connector +#: ../../../connector.pydocstring of +#: connector.connector.ConnectorEnvironment:12 +msgid "" +"Browsable record of the backend. The backend is inherited from the model " +"``connector.backend`` and have at least a ``type`` and a ``version``." +msgstr "" +"Enregistrement de type `browse` pour le backend. Le backend est hérité du " +"modèle ``connector.backend`` et a au moins un ``type`` et une ``version``." + +#. module: connector +#: ../../../connector.pydocstring of +#: connector.connector.ConnectorEnvironment:18 +msgid "" +"Current session we are working in. It contains the Odoo cr, uid and " +"context." +msgstr "" +"Session en cours sur laquelle on travaille. Elle contient les ``cr``, " +"``uid`` et ``context`` d'Odoo." + +#. module: connector +#: ../../../connector.pydocstring of +#: connector.connector.ConnectorEnvironment:23 +msgid "Name of the Odoo model to work with." +msgstr "Nom du modèle Odoo avec lequel travailler." + +#. module: connector +#: ../../../connector.pydocstring of +#: connector.connector.ConnectorEnvironment.get_connector_unit:1 +msgid "" +"Searches and returns an instance of the " +":py:class:`~connector.connector.ConnectorUnit` for the current model and " +"being a class or subclass of ``base_class``." +msgstr "" +"Recherche et renvoie une instance de " +":py:class:`~connector.connector.ConnectorUnit` pour le modèle en cours et " +"étant une classe ou sous-classe de ``base_class``." + +#. module: connector +#: ../../../connector.pydocstring of +#: connector.connector.ConnectorEnvironment.get_connector_unit:5 +msgid "The returned instance is built with ``self`` for its environment." +msgstr "" +"L'instance renvoyée est construite avec ``self`` pour son environnement." + +#. module: connector +#: ../../../connector.pydocstring of +#: connector.connector.ConnectorEnvironment.get_connector_unit:7 +#: ../../../connector.pydocstring of +#: connector.connector.ConnectorUnit.unit_for:11 +msgid "``ConnectorUnit`` to search (class or subclass)" +msgstr "``ConnectorUnit`` à rechercher (classe ou sous-classe)" + +#. module: connector +#: ../../../connector.pydocstring of +#: connector.connector.ConnectorEnvironment.set_lang:1 +msgid "Change the working language in the environment." +msgstr "Change la langue de travail dans l'environnement." + +#. module: connector +#: ../../../connector.pydocstring of +#: connector.connector.ConnectorEnvironment.set_lang:3 +msgid "It changes the ``lang`` key in the session's context." +msgstr "Ceci change la clé ``lang`` dans le ``context`` de la session." + +#. module: connector +#: ../../../connector.pydocstring of connector.connector.ConnectorUnit:1 +msgid "Abstract class for each piece of the connector:" +msgstr "Classe abstraite pour chaque composant du connecteur :" + +#. module: connector +#: ../../../connector.pydocstring of connector.connector.ConnectorUnit:7 +msgid "Examples:" +msgstr "Exemples :" + +#. module: connector +#: ../../../connector.pydocstring of connector.connector.ConnectorUnit:4 +msgid ":py:class:`connector.connector.Binder`" +msgstr ":py:class:`connector.connector.Binder`" + +#. module: connector +#: ../../../connector.pydocstring of connector.connector.ConnectorUnit:5 +#: ../../../unit/synchronizer.pydocstring of +#: connector.unit.synchronizer.Synchronizer.mapper:6 +msgid ":py:class:`connector.unit.mapper.Mapper`" +msgstr ":py:class:`connector.unit.mapper.Mapper`" + +#. module: connector +#: ../../../connector.pydocstring of connector.connector.ConnectorUnit:6 +msgid ":py:class:`connector.unit.synchronizer.Synchronizer`" +msgstr ":py:class:`connector.unit.synchronizer.Synchronizer`" + +#. module: connector +#: ../../../connector.pydocstring of connector.connector.ConnectorUnit:7 +#: ../../../unit/synchronizer.pydocstring of +#: connector.unit.synchronizer.Synchronizer.backend_adapter:7 +msgid ":py:class:`connector.unit.backend_adapter.BackendAdapter`" +msgstr ":py:class:`connector.unit.backend_adapter.BackendAdapter`" + +#. module: connector +#: ../../../connector.pydocstring of connector.connector.ConnectorUnit:9 +msgid "" +"Or basically any class intended to be registered in a " +":py:class:`~connector.backend.Backend`." +msgstr "" +"Ou en gros n'importe quelle classe destinée à être inscrite dans un " +":py:class:`~connector.backend.Backend`." + +#. module: connector +#: ../../../connector.pydocstring of +#: connector.connector.ConnectorUnit.binder_for:1 +#: ../../../connector.pydocstring of +#: connector.connector.ConnectorUnit.get_binder_for_model:1 +msgid "Returns an new instance of the correct ``Binder`` for a model" +msgstr "Renvoie une nouvelle instance du bon ``Binder`` pour un modèle" + +#. module: connector +#: ../../../connector.pydocstring of connector.connector.ConnectorUnit.env:1 +msgid "Returns the odoo.api.environment" +msgstr "Renvoie le odoo.api.environment" + +#. module: connector +#: ../../../connector.pydocstring of +#: connector.connector.ConnectorUnit.get_binder_for_model:4 +msgid "Deprecated, use ``binder_for`` now." +msgstr "Déprécié, utilisez maintenant ``binder_for``." + +#. module: connector +#: ../../../connector.pydocstring of +#: connector.connector.ConnectorUnit.get_connector_unit_for_model:1 +msgid "Deprecated in favor of :meth:`~unit_for`" +msgstr "Déprécié en faveur de :meth:`~unit_for`" + +#. module: connector +#: ../../../connector.pydocstring of +#: connector.connector.ConnectorUnit.localcontext:1 +msgid "It is there for compatibility." +msgstr "Présent pour une question de compatibilité." + +#. module: connector +#: ../../../connector.pydocstring of +#: connector.connector.ConnectorUnit.localcontext:3 +msgid "" +":func:`odoo.tools.translate._` searches for this attribute in the classes" +" do be able to translate the strings." +msgstr "" +":func:`odoo.tools.translate._` recherche cet attribut dans les classes " +"pour être capable de traduire les chaînes." + +#. module: connector +#: ../../../connector.pydocstring of +#: connector.connector.ConnectorUnit.localcontext:6 +msgid "There is no reason to use this attribute for other purposes." +msgstr "Il n'y a aucune raison d'utiliser cet attribut à d'autres fins." + +#. module: connector +#: ../../../connector.pydocstring of connector.connector.ConnectorUnit.match:1 +msgid "Returns True if the current class correspond to the searched model." +msgstr "Renvoie True si la classe en cours correspond au modèle recherché" + +#. module: connector +#: ../../../connector.pydocstring of connector.connector.ConnectorUnit.match:6 +msgid "model to match" +msgstr "modèle à rechercher" + +#. module: connector +#: ../../../connector.pydocstring of +#: connector.connector.ConnectorUnit.unit_for:1 +msgid "" +"According to the current " +":py:class:`~connector.connector.ConnectorEnvironment`, search and returns an" +" instance of the :py:class:`~connector.connector.ConnectorUnit` for the " +"current model and being a class or subclass of ``connector_unit_class``." +msgstr "" +"Selon le :py:class:`~connector.connector.ConnectorEnvironment` en cours, " +"recherche et renvoie une instance de " +":py:class:`~connector.connector.ConnectorUnit` pour le modèle actuel et " +"étant une classe ou sous-classe de ``connector_unit_class``." + +#. module: connector +#: ../../../connector.pydocstring of +#: connector.connector.ConnectorUnit.unit_for:7 +msgid "" +"If a different ``model`` is given, a new " +":py:class:`~connector.connector.ConnectorEnvironment` is built for this " +"model." +msgstr "" +"Si un ``model`` différent est donné, un nouveau " +":py:class:`~connector.connector.ConnectorEnvironment` est construit pour ce " +"modèle." + +#. module: connector +#: ../../../connector.pydocstring of +#: connector.connector.ConnectorUnit.unit_for:14 +msgid "" +"to give if the ``ConnectorUnit`` is for another model than the current one" +msgstr "" +"à donner si le ``ConnectorUnit`` est pour un autre modèle que le modèle " +"actuel" + +#. module: connector +#: ../../../connector.pydocstring of connector.connector.MetaConnectorUnit:1 +msgid "Bases: :class:`type`" +msgstr "Bases : :class:`type`" + +#. module: connector +#: ../../../connector.pydocstring of connector.connector.MetaConnectorUnit:1 +msgid "Metaclass for ConnectorUnit." +msgstr "Metaclass pour ConnectorUnit." + +#. module: connector +#: ../../../connector.pydocstring of connector.connector.MetaConnectorUnit:3 +msgid "" +"Keeps a ``_module`` attribute on the classes, the same way Odoo does it " +"for the Model classes. It is then used to filter them according to the state" +" of the module (installed or not)." +msgstr "" +"Conserve un attribut ``_module`` sur les classes, de la même façon " +"qu'Odoo pour les classes de modèles. Il est utilisé ensuite pour les " +"filtrer en fonction de l'état du module (installé ou non)." + +#. module: connector +#: ../../../connector.pydocstring of +#: connector.connector.MetaConnectorUnit.for_model_names:1 +msgid "" +"Returns the list of models on which a " +":class:`~connector.connector.ConnectorUnit` is usable" +msgstr "" +"Renvoie une liste de modèles sur lesquels une " +":class:`~connector.connector.ConnectorUnit` est utilisable" + +#. module: connector +#: ../../../connector.pydocstring of +#: connector.connector.MetaConnectorUnit.for_model_names:4 +msgid "" +"It is used in :meth:`~connector.connector.ConnectorUnit.match` when we " +"search the correct ``ConnectorUnit`` for a model." +msgstr "" +"Utilisé dans :meth:`~connector.connector.ConnectorUnit.match` lorsqu'on " +"recherche la bonne ``ConnectorUnit`` pour un modèle." + +#. module: connector +#: ../../../connector.pydocstring of connector.connector.get_odoo_module:1 +msgid "" +"For a top level function or class, returns the name of the Odoo module " +"where it lives." +msgstr "" +"Pour une fonction ou classe de niveau supérieur, renvoie le nom du module " +"Odoo où elle réside." + +#. module: connector +#: ../../../connector.pydocstring of connector.connector.get_odoo_module:4 +msgid "" +"So we will be able to filter them according to the modules installation " +"state." +msgstr "" +"Ainsi nous serons capable de les filtrer en fonction de l'état " +"d'installation des modules." + +#. module: connector +#: ../../api/api_event.rst:2 +msgid "Event" +msgstr "Événement" + +#. module: connector +#: ../../../event.pydocstring of connector.event.Event:1 +msgid "An event contains consumers called when the event is fired." +msgstr "" +"Un événement contient des consommateurs qui sont appelés lorsque l'événement" +" survient." + +#. module: connector +#: ../../../event.pydocstring of connector.event.Event:3 +msgid "The events are able to filter the consumers to execute by model name." +msgstr "" +"Les événements sont capables de filtrer par nom de modèle les consommateurs " +"à exécuter." + +#. module: connector +#: ../../../event.pydocstring of connector.event.Event:5 +msgid "The usage of an event is to instantiate an `Event` object::" +msgstr "L'usage classique d'un événement est d'instancier un objet `Event` ::" + +#. module: connector +#: ../../../event.pydocstring of connector.event.Event:9 +msgid "An event always have at least the 2 following arguments:" +msgstr "Un événement a toujours au moins les deux arguments suivants :" + +#. module: connector +#: ../../../event.pydocstring of connector.event.Event:11 +#: ../../../queue/job.pydocstring of connector.queue.job.job:13 +msgid "session" +msgstr "session" + +#. module: connector +#: ../../../event.pydocstring of connector.event.Event:12 +#: ../../../queue/job.pydocstring of connector.queue.job.job:16 +msgid "model_name" +msgstr "model_name" + +#. module: connector +#: ../../../event.pydocstring of connector.event.Event:40 +msgid "Finally, we fire the event::" +msgstr "Finalement, on déclenche l'événement ::" + +#. module: connector +#: ../../../event.pydocstring of connector.event.Event:44 +msgid "A consumer can be subscribed using a decorator::" +msgstr "Un consommateur peut être inscrit grâce à un décorateur ::" + +#. module: connector +#: ../../../event.pydocstring of connector.event.Event.fire:1 +msgid "" +"Call each consumer subscribed on the event with the given arguments and " +"keyword arguments." +msgstr "" +"Appelle chaque consommateur inscrit à l'événement avec les arguments " +"positionnels et arguments nommés fournis." + +#. module: connector +#: ../../../event.pydocstring of connector.event.Event.fire:4 +msgid "" +"All the consumers which were subscribed globally (no model name) or which " +"are subscribed on the same model" +msgstr "" +"Tous les consommateurs qui sont abonnés de manière globale (sans nom de " +"modèle) ou qui sont abonnés au même modèle" + +#. module: connector +#: ../../../event.pydocstring of connector.event.Event.fire:9 +msgid "name of the model" +msgstr "nom du modèle" + +#. module: connector +#: ../../../event.pydocstring of connector.event.Event.fire:11 +msgid "" +"arguments propagated to the consumer The second argument of `args` is the " +"model name. The first argument is the session." +msgstr "" +"arguments propagés au consommateur. Le deuxième argument de `args` est le " +"nom de modèle. Le premier argument est la session." + +#. module: connector +#: ../../../event.pydocstring of connector.event.Event.fire:14 +msgid "keyword arguments propagated to the consumer" +msgstr "arguments nommés propagés au consommateur" + +#. module: connector +#: ../../../event.pydocstring of connector.event.Event.has_consumer_for:1 +msgid "Return True if at least one consumer is registered for the model." +msgstr "Renvoie True si au moins un consommateur est abonné pour ce modèle." + +#. module: connector +#: ../../../event.pydocstring of connector.event.Event.subscribe:1 +msgid "Subscribe a consumer on the event" +msgstr "Abonne un consommateur à l'événement" + +#. module: connector +#: ../../../event.pydocstring of connector.event.Event.subscribe:3 +msgid "the function to register on the event" +msgstr "la fonction à abonner à l'événement" + +#. module: connector +#: ../../../event.pydocstring of connector.event.Event.subscribe:4 +msgid "" +"the consumer will be active only on these models, active on all models if " +"``None``" +msgstr "" +"le consommateur sera actif seulement sur ces modèles ou, si ``None``, actifs" +" sur tous les modèles" + +#. module: connector +#: ../../../event.pydocstring of connector.event.Event.subscribe:6 +msgid "the function beeing replaced by this new one." +msgstr "la fonction à remplacer par la nouvelle." + +#. module: connector +#: ../../../event.pydocstring of connector.event.Event.unsubscribe:1 +msgid "Remove a consumer from the event" +msgstr "Retire un consommateur d'un événement" + +#. module: connector +#: ../../../event.pydocstring of connector.event.Event.unsubscribe:3 +msgid "the function to unsubscribe" +msgstr "la fonction à désinscrire" + +#. module: connector +#: ../../../event.pydocstring of connector.event.Event.unsubscribe:4 +msgid "" +"remove only for these models or remove a consumer which is active on all " +"models if ``None``." +msgstr "" +"retire seulement pour ces modèles ou, si ``None``, retire un consommateur " +"qui est actif sur tous les modèles" + +#. module: connector +#: ../../../event.pydocstring of connector.event.on_record_create:1 +msgid "``on_record_create`` is fired when one record has been created." +msgstr "``on_record_create`` est déclenché à la création d'un enregistrement." + +#. module: connector +#: ../../../event.pydocstring of connector.event.on_record_create:3 +#: ../../../event.pydocstring of connector.event.on_record_unlink:3 +#: ../../../event.pydocstring of connector.event.on_record_write:3 +msgid "Listeners should take the following arguments:" +msgstr "Les abonnés doivent prendre les arguments suivants :" + +#. module: connector +#: ../../../event.pydocstring of connector.event.on_record_create:5 +#: ../../../event.pydocstring of connector.event.on_record_unlink:5 +#: ../../../event.pydocstring of connector.event.on_record_write:5 +msgid "session: :py:class:`~connector.session.ConnectorSession` object" +msgstr "session : objet :py:class:`~connector.session.ConnectorSession`" + +#. module: connector +#: ../../../event.pydocstring of connector.event.on_record_create:6 +#: ../../../event.pydocstring of connector.event.on_record_unlink:6 +#: ../../../event.pydocstring of connector.event.on_record_write:6 +msgid "model_name: name of the model" +msgstr "model_name : nom du modèle" + +#. module: connector +#: ../../../event.pydocstring of connector.event.on_record_create:7 +msgid "record_id: id of the created record" +msgstr "record_id : Id de l'enregistrement créé" + +#. module: connector +#: ../../../event.pydocstring of connector.event.on_record_create:8 +msgid "vals: field values updated, e.g {'field_name': field_value, ...}" +msgstr "" +"vals : valeurs des champs mis à jour, par ex. {'field_name': field_value, " +"...}" + +#. module: connector +#: ../../../event.pydocstring of connector.event.on_record_unlink:1 +msgid "``on_record_unlink`` is fired when one record has been deleted." +msgstr "" +"``on_record_unlink`` est déclenché à la suppression d'un enregistrement." + +#. module: connector +#: ../../../event.pydocstring of connector.event.on_record_unlink:7 +#: ../../../event.pydocstring of connector.event.on_record_write:7 +msgid "record_id: id of the record" +msgstr "record_id : Id de l'enregistrement" + +#. module: connector +#: ../../../event.pydocstring of connector.event.on_record_write:1 +msgid "``on_record_write`` is fired when one record has been updated." +msgstr "" +"``on_record_write`` est déclenché à la mise à jour d'un enregistrement." + +#. module: connector +#: ../../../event.pydocstring of connector.event.on_record_write:8 +msgid "" +"vals: field values of the new record, e.g {'field_name': field_value, ...}" +msgstr "" +"vals : valeurs des champ pour le nouvel enregistrement, par ex. " +"{'field_name': field_value, ...}" + +#. module: connector +#: ../../api/api_exception.rst:2 +msgid "Exceptions" +msgstr "Exceptions" + +#. module: connector +#: ../../../exception.pydocstring of connector.exception.ConnectorException:1 +msgid "Bases: :class:`exceptions.RuntimeError`" +msgstr "Bases : :class:`exceptions.RuntimeError`" + +#. module: connector +#: ../../../exception.pydocstring of connector.exception.ConnectorException:1 +msgid "Base Exception for the connectors" +msgstr "Exception de base pour les connecteurs" + +#. module: connector +#: ../../../exception.pydocstring of connector.exception.FailedJobError:1 +#: ../../../exception.pydocstring of connector.exception.IDMissingInBackend:1 +#: ../../../exception.pydocstring of connector.exception.ManyIDSInBackend:1 +#: ../../../exception.pydocstring of connector.exception.NoSuchJobError:1 +#: ../../../exception.pydocstring of connector.exception.NotReadableJobError:1 +#: ../../../exception.pydocstring of connector.exception.NothingToDoJob:1 +#: ../../../exception.pydocstring of connector.exception.RetryableJobError:1 +msgid "Bases: :class:`connector.exception.JobError`" +msgstr "Bases : :class:`connector.exception.JobError`" + +#. module: connector +#: ../../../exception.pydocstring of connector.exception.FailedJobError:1 +msgid "A job had an error having to be resolved." +msgstr "Un job a eu une erreur qui doit être résolue" + +#. module: connector +#: ../../../exception.pydocstring of connector.exception.InvalidDataError:1 +#: ../../../exception.pydocstring of connector.exception.JobError:1 +#: ../../../exception.pydocstring of connector.exception.MappingError:1 +#: ../../../exception.pydocstring of +#: connector.exception.NoConnectorUnitError:1 +msgid "Bases: :class:`connector.exception.ConnectorException`" +msgstr "Bases : :class:`connector.exception.ConnectorException`" + +#. module: connector +#: ../../../exception.pydocstring of connector.exception.InvalidDataError:1 +msgid "Data Invalid" +msgstr "Donnée incorrecte" + +#. module: connector +#: ../../../exception.pydocstring of connector.exception.JobError:1 +msgid "A job had an error" +msgstr "Un job a eu une erreur" + +#. module: connector +#: ../../../exception.pydocstring of connector.exception.ManyIDSInBackend:1 +msgid "Unique key exists many times in backend" +msgstr "Une clé unique existe plusieurs fois dans le backend" + +#. module: connector +#: ../../../exception.pydocstring of connector.exception.MappingError:1 +msgid "An error occurred during a mapping transformation." +msgstr "Une erreur est survenue pendant une transformation de mapping" + +#. module: connector +#: ../../../exception.pydocstring of +#: connector.exception.NetworkRetryableError:1 ../../../exception.pydocstring +#: of connector.exception.NoExternalId:1 +msgid "Bases: :class:`connector.exception.RetryableJobError`" +msgstr "Bases : :class:`connector.exception.RetryableJobError`" + +#. module: connector +#: ../../../exception.pydocstring of +#: connector.exception.NetworkRetryableError:1 +msgid "" +"A network error caused the failure of the job, it can be retried later." +msgstr "" +"Une erreur de réseau a causé l'échec du job, il peut être réessayé plus " +"tard." + +#. module: connector +#: ../../../exception.pydocstring of +#: connector.exception.NoConnectorUnitError:1 +msgid "No ConnectorUnit has been found" +msgstr "Aucune ConnectorUnit n'a été trouvé" + +#. module: connector +#: ../../../exception.pydocstring of connector.exception.NoExternalId:1 +msgid "No External ID found, it can be retried later." +msgstr "Aucun ID Externe trouvé. Peut être réessayé plus tard." + +#. module: connector +#: ../../../exception.pydocstring of connector.exception.NoSuchJobError:1 +msgid "The job does not exist." +msgstr "Le job n'existe pas." + +#. module: connector +#: ../../../exception.pydocstring of connector.exception.NotReadableJobError:1 +msgid "The job cannot be read from the storage." +msgstr "Le job ne peut pas être lu depuis l'espace de stockage." + +#. module: connector +#: ../../../exception.pydocstring of connector.exception.NothingToDoJob:1 +msgid "The Job has nothing to do." +msgstr "Le job n'a rien à faire." + +#. module: connector +#: ../../../exception.pydocstring of connector.exception.RetryableJobError:1 +msgid "A job had an error but can be retried." +msgstr "Un job a eu une erreur mais peut être réessayé." + +#. module: connector +#: ../../api/api_mapper.rst:2 +msgid "Mapper" +msgstr "Mappeur" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper:2 +msgid "Mappers" +msgstr "Mappeurs" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper:4 +msgid "" +"Mappers are the ConnectorUnit classes responsible to transform external " +"records into Odoo records and conversely." +msgstr "" +"Les Mappeurs sont les classes ConnectorUnit responsables de la " +"transformation d'un enregistrement externe vers un enregistrement Odoo et" +" vice versa." + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.ExportMapChild:1 +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.ImportMapChild:1 +msgid "Bases: :class:`connector.unit.mapper.MapChild`" +msgstr "Bases : :class:`connector.unit.mapper.MapChild`" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.ExportMapChild:1 +msgid ":py:class:`MapChild` for the Exports" +msgstr ":py:class:`MapChild` pour les exports" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.ExportMapper:1 +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.ImportMapper:1 +msgid "Bases: :class:`connector.unit.mapper.Mapper`" +msgstr "Bases : :class:`connector.unit.mapper.Mapper`" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.ExportMapper:1 +msgid ":py:class:`Mapper` for exports." +msgstr ":py:class:`Mapper` pour les exports." + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.ExportMapper:3 +msgid "Transform a record from Odoo to a backend record" +msgstr "" +"Transforme un enregistrement depuis Odoo vers un enregistrement du " +"backend" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.ImportMapChild:1 +msgid ":py:class:`MapChild` for the Imports" +msgstr ":py:class:`MapChild` pour les imports" + +#. module: connector +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.ImportMapChild.format_items:1 +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.MapChild.format_items:1 +msgid "Format the values of the items mapped from the child Mappers." +msgstr "Formate les valeurs des items mappés depuis les Mappeurs enfants." + +#. module: connector +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.ImportMapChild.format_items:3 +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.MapChild.format_items:3 +msgid "" +"It can be overridden for instance to add the Odoo relationships commands " +"``(6, 0, [IDs])``, ..." +msgstr "" +"Il peut être surchargé par exemple pour ajouter les commandes de relation " +"d'Odoo ``(6, 0, [IDs])``, ..." + +#. module: connector +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.ImportMapChild.format_items:6 +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.MapChild.format_items:6 +msgid "" +"As instance, it can be modified to handle update of existing items: check if" +" an 'id' has been defined by :py:meth:`get_item_values` then use the ``(1, " +"ID, {values}``) command" +msgstr "" +"Par exemple, il peut être modifié pour pour gérer la mise à jour d'items " +"existants : vérifier si un 'id' a bien été défini par " +":py:meth:`get_item_values` puis utilise la commande ``(1, ID, {valeurs}``)" + +#. module: connector +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.ImportMapChild.format_items:11 +msgid "list of values for the items to create" +msgstr "liste des valeurs pour les items à créer" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.ImportMapper:1 +msgid ":py:class:`Mapper` for imports." +msgstr ":py:class:`Mapper` pour les imports." + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.ImportMapper:3 +msgid "Transform a record from a backend to an Odoo record" +msgstr "" +"Transforme un enregistrement depuis un backend vers un enregistrement " +"Odoo" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.MapChild:1 +msgid "MapChild is responsible to convert items." +msgstr "MapChild est responsable de la conversion des items." + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.MapChild:3 +msgid "" +"Items are sub-records of a main record. In this example, the items are the " +"records in ``lines``::" +msgstr "" +"Les items sont des sous-enregistrements d'un enregistrement principal. Dans " +"cet exemple, les items sont les enregistrements qui sont dans ``lines`` ::" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.MapChild:10 +msgid "" +"A MapChild is always called from another :py:class:`Mapper` which provides a" +" ``children`` configuration." +msgstr "" +"Un MapChild est toujours appelé depuis un autre :py:class:`Mapper` qui " +"fournit une configuration ``children``." + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.MapChild:13 +msgid "" +"Considering the example above, the \"main\" :py:class:`Mapper` would returns" +" something as follows::" +msgstr "" +"Compte tenu de l'exemple ci-dessus, le :py:class:`Mapper` « principal » " +"renverrait quelque chose comme ça ::" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.MapChild:20 +msgid "A MapChild is responsible to:" +msgstr "Un MapChild est responsable de :" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.MapChild:22 +msgid "Find the :py:class:`Mapper` to convert the items" +msgstr "Trouver le :py:class:`Mapper` pour convertir les items" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.MapChild:25 +msgid "Convert the items' records using the found :py:class:`Mapper`" +msgstr "" +"Convertir les enregistrements des items en utilisant le :py:class:`Mapper` " +"trouvé" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.MapChild:26 +msgid "" +"Format the output values to the format expected by Odoo or the backend " +"(as seen above with ``(0, 0, {values})``" +msgstr "" +"Formater les valeurs de sortie vers le format attendu par Odoo ou par le " +"backend (comme vu ci-dessus avec ``(0, 0, {values})``" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.MapChild:29 +msgid "" +"A MapChild can be extended like any other " +":py:class:`~connector.connector.ConnectorUnit`. However, it is not mandatory" +" to explicitly create a MapChild for each children mapping, the default one " +"will be used (:py:class:`ImportMapChild` or :py:class:`ExportMapChild`)." +msgstr "" +"Un MapChild peut être étendu comme toute autre " +":py:class:`~connector.connector.ConnectorUnit`. Cependant il n'est pas " +"nécessaire de créer un MapChild pour chaque mappeur enfant, ceux par défaut " +"seront utilisés (:py:class:`ImportMapChild` ou :py:class:`ExportMapChild`)." + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.MapChild:35 +msgid "" +"The implementation by default does not take care of the updates: if I import" +" a sales order 2 times, the lines will be duplicated. This is not a problem " +"as long as an importation should only support the creation (typical for " +"sales orders). It can be implemented on a case-by-case basis by inheriting " +":py:meth:`get_item_values` and :py:meth:`format_items`." +msgstr "" +"L'implémentation par défaut ne gère pas les mises à jour : si j'importe une " +"commande deux fois, les lignes seront dupliquées. Ceci n'est pas un problème" +" à condition qu'un import ne prenne en charge que la création (typique pour" +" les commandes). Il peut être implémenté au cas par cas en héritant de " +":py:meth:`get_item_values` et :py:meth:`format_items`." + +#. module: connector +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.MapChild.format_items:11 +msgid "mapped values for the items" +msgstr "valeurs traduites pour les items" + +#. module: connector +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.MapChild.get_item_values:1 +msgid "Get the raw values from the child Mappers for the items." +msgstr "Récupère la valeur brute des Mappeurs enfants depuis les items." + +#. module: connector +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.MapChild.get_item_values:3 +msgid "It can be overridden for instance to:" +msgstr "I peut être surchargé par exemple pour :" + +#. module: connector +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.MapChild.get_item_values:5 +msgid "Change options" +msgstr "Changer des options" + +#. module: connector +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.MapChild.get_item_values:6 +msgid "" +"Use a :py:class:`~connector.connector.Binder` to know if an item already " +"exists to modify an existing item, rather than to add it" +msgstr "" +"Utiliser un :py:class:`~connector.connector.Binder` pour savoir si un item " +"existe déjà afin de le modifier au lieu de l'ajouter" + +#. module: connector +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.MapChild.get_item_values:10 +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.MapChild.skip_item:7 +msgid "record that we are converting" +msgstr "enregistrement que nous sommes en train de convertir" + +#. module: connector +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.MapChild.get_item_values:12 +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.MapChild.get_items:6 +msgid "destination field (can be used for introspecting the relation)" +msgstr "champ destination (peut être utilisé pour inspecter la relation)" + +#. module: connector +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.MapChild.get_item_values:15 +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.MapChild.get_items:9 +msgid "dict of options, herited from the main mapper" +msgstr "dictionnaire des options, hérité du mappeur principal" + +#. module: connector +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.MapChild.get_items:1 +msgid "Returns the formatted output values of items from a main record" +msgstr "" +"Renvoie la sortie formatée des valeurs des items pour un enregistrement " +"principal" + +#. module: connector +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.MapChild.get_items:3 +msgid "list of item records" +msgstr "liste d'enregistrements d'items" + +#. module: connector +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.MapChild.get_items:5 +msgid "parent record" +msgstr "enregistrement parent" + +#. module: connector +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.MapChild.get_items:10 +msgid "formatted output values for the item" +msgstr "valeurs de sortie formatées pour l'item" + +#. module: connector +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.MapChild.skip_item:1 +msgid "" +"Hook to implement in sub-classes when some child records should be skipped." +msgstr "" +"Point d'accroche à implémenter dans les sous-classes lorsque certains " +"enregistrements enfants doivent être sautés." + +#. module: connector +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.MapChild.skip_item:4 +msgid "" +"The parent record is accessible in ``map_record``. If it returns True, the " +"current child record is skipped." +msgstr "" +"L'enregistrement parent est accessible dans ``map_record``. S'il renvoie " +"True, l'enregistrement enfant en cours est sauté." + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.MapOptions:1 +msgid "Bases: :class:`dict`" +msgstr "Bases : :class:`dict`" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.MapOptions:1 +msgid "Container for the options of mappings." +msgstr "Conteneur pour les options des mappeurs." + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.MapOptions:3 +msgid "" +"Options can be accessed using attributes of the instance. When an option is" +" accessed and does not exist, it returns None." +msgstr "" +"Des options peuvent être accédées grâce aux attributs de l'instance. Quand " +"une option est accédée mais n'existe pas, ceci renvoie None." + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.MapRecord:1 +msgid "A record prepared to be converted using a :py:class:`Mapper`." +msgstr "" +"Un enregistrement préparé à être converti en utilisans un " +":py:class:`Mapper`." + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.MapRecord:3 +msgid "MapRecord instances are prepared by :py:meth:`Mapper.map_record`." +msgstr "" +"Les instances de MapRecord sont préparées par :py:meth:`Mapper.map_record`." + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.MapRecord:5 +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.MapRecord.update:3 ../../../unit/mapper.pydocstring +#: of connector.unit.mapper.MapRecord.values:3 +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.changed_by:14 +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.mapping:5 +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.only_create:6 +#: ../../../session.pydocstring of +#: connector.session.ConnectorSessionHandler:16 +msgid "Usage::" +msgstr "Utilisation ::" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.MapRecord:11 +msgid "See :py:meth:`values` for more information on the available arguments." +msgstr "" +"Voir :py:meth:`values` pour avoir plus d'informations sur les arguments " +"disponibles." + +#. module: connector +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.MapRecord.parent:1 +msgid "Parent record if the current record is an item" +msgstr "Enregistrement parent si l'enregistrement en cours est un item" + +#. module: connector +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.MapRecord.source:1 +msgid "Source record to be converted" +msgstr "Enregistrement source à convertir" + +#. module: connector +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.MapRecord.update:1 +msgid "Force values to be applied after a mapping." +msgstr "Force des valeurs à appliquer après une conversion." + +#. module: connector +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.MapRecord.update:11 +msgid "" +"The values assigned with ``update()`` are in any case applied, they have a " +"greater priority than the mapping values." +msgstr "" +"Les valeurs affectées avec ``update()`` sont appliquées dans tous les cas, " +"elles ont une priorité supérieure que les valeurs converties." + +#. module: connector +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.MapRecord.values:1 +msgid "Build and returns the mapped values according to the options." +msgstr "Construit et renvoie les valeurs converties selon les options." + +#. module: connector +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.MapRecord.values:15 +msgid "Creation of records" +msgstr "Création des enregistrements" + +#. module: connector +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.MapRecord.values:10 +msgid "" +"When using the option ``for_create``, only the mappings decorated with " +"``@only_create`` will be mapped." +msgstr "" +"En utilisant l'option ``for_create``, seuls les mappings décorés avec " +"``@only_create`` seront mappés." + +#. module: connector +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.MapRecord.values:24 +msgid "Filter on fields" +msgstr "Filtrer sur les champs" + +#. module: connector +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.MapRecord.values:18 +msgid "" +"When using the ``fields`` argument, the mappings will be filtered using " +"either the source key in ``direct`` arguments, either the ``changed_by`` " +"arguments for the mapping methods." +msgstr "" +"En utilisant l'argument ``fields``, les mappings seront filtrés en utilisant" +" soit la clé source dans les arguments ``direct``, soit les arguments " +"``changed_by`` pour les méthodes de mapping." + +#. module: connector +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.MapRecord.values:33 +msgid "Custom options" +msgstr "Options spécifiques" + +#. module: connector +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.MapRecord.values:27 +msgid "" +"Arbitrary key and values can be defined in the ``kwargs`` arguments. They " +"can later be used in the mapping methods using ``self.options``." +msgstr "" +"Des clé et valeurs arbitraires peuvent être définies dans les arguments " +"``kwargs``. Elles peuvent être ensuites utilisées dans les méthodes de " +"mapping en utilisant ``self.options``." + +#. module: connector +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.MapRecord.values:35 +msgid "" +"specify if only the mappings for creation (``@only_create``) should be " +"mapped." +msgstr "" +"précise si seuls les mappings de création (``@only_create``) doivent être " +"mappés." + +#. module: connector +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.MapRecord.values:38 +msgid "filter on fields" +msgstr "filtre sur les champs" + +#. module: connector +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.MapRecord.values:40 ../../../unit/mapper.pydocstring +#: of connector.unit.mapper.MapRecord.values:40 +msgid "custom options, they can later be used in the mapping methods" +msgstr "" +"options spécifiques, elles peuvent être utilisées plus tard dans les " +"méthodes de mapping" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.Mapper:1 +msgid "" +"A Mapper translates an external record to an Odoo record and conversely. " +"The output of a Mapper is a ``dict``." +msgstr "" +"Un Mappeur convertit un enregistrement externe en enregistrement Odoo et " +"vice versa. La sortie d'un Traducteur est un ``dict``." + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.Mapper:4 +msgid "3 types of mappings are supported:" +msgstr "3 types de mappings sont pris en charge :" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.Mapper:55 +msgid "Direct Mappings" +msgstr "Mappings directs" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.Mapper:7 +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.backend_to_m2o:10 +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.convert:5 +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.m2o_to_backend:9 +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.none:6 +msgid "Example::" +msgstr "Exemples ::" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.Mapper:11 +msgid "Here, the ``source`` field will be copied in the ``target`` field." +msgstr "Ici le champs ``source`` sera copié vers le champ ``target``." + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.Mapper:13 +msgid "" +"A modifier can be used in the source item. The modifier will be applied to " +"the source field before being copied in the target field. It should be a " +"closure function respecting this idiom::" +msgstr "" +"Un modificateur peut être utilisé dans l'item source. Le modificateur sera " +"appliqué au champ source avant d'être copié dans le champ destination. Il " +"doit être une fonction de type `closure` pour respecter cet idiome ::" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.Mapper:27 +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.Mapper:45 +msgid "And used like that::" +msgstr "Et utilisé de cette façon ::" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.Mapper:33 +msgid "A more concrete example of modifier::" +msgstr "Un exemple plus concret de modificateur ::" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.Mapper:51 +msgid "More examples of modifiers:" +msgstr "D'autres exemples de modificateurs ::" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.Mapper:53 +msgid ":py:func:`convert`" +msgstr ":py:func:`convert`" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.Mapper:54 +msgid ":py:func:`m2o_to_backend`" +msgstr ":py:func:`m2o_to_backend`" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.Mapper:55 +msgid ":py:func:`backend_to_m2o`" +msgstr ":py:func:`backend_to_m2o`" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.Mapper:76 +msgid "Method Mappings" +msgstr "Mappings par méthode" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.Mapper:58 +msgid "" +"A mapping method allows to execute arbitrary code and return one or many " +"fields::" +msgstr "" +"Un méthode de mapping permet d'exécuter un code arbitraire et de renvoyer un" +" ou plusieurs champs ::" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.Mapper:67 +msgid "" +"We can also specify that a mapping methods should be applied only when an " +"object is created, and never applied on further updates::" +msgstr "" +"Nous pouvons aussi préciser qu'une méthode de mapping doit être appliquée " +"lorsqu'un objet est créé, mais jamais appliquée sur les mises à jour " +"ultérieures ::" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.Mapper:89 +msgid "Submappings" +msgstr "Sous-mappings" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.Mapper:79 +msgid "" +"When a record contains sub-items, like the lines of a sales order, we can " +"convert the children using another Mapper::" +msgstr "" +"Lorsqu'un enregistrement contient des sous-items, comme les lignes d'une " +"commande, nous pouvons convertir les enfants grâce à une autre Mappeur ::" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.Mapper:84 +msgid "" +"It allows to create the sales order and all its lines with the same call to " +":py:meth:`odoo.models.BaseModel.create()`." +msgstr "" +"Il permet de créer des commandes et toutes ses lignes dans le même appel à " +":py:meth:`odoo.models.BaseModel.create()`." + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.Mapper:87 +msgid "" +"When using ``children`` for items of a record, we need to create a " +":py:class:`Mapper` for the model of the items, and optionally a " +":py:class:`MapChild`." +msgstr "" +"En utilisant des ``children`` pour les items d'un enregistrement, nous " +"devons créer un :py:class:`Mapper` pour le modèle des items, et de manière " +"optionnelle un :py:class:`MapChild`." + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.Mapper:91 +msgid "Usage of a Mapper::" +msgstr "Utilisation d'un Mappeur ::" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.Mapper.finalize:1 +msgid "Called at the end of the mapping." +msgstr "Appelé à la fin du mapping." + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.Mapper.finalize:3 +msgid "" +"Can be used to modify the values before returning them, as the " +"``on_change``." +msgstr "" +"Peut être utilisé pour modifier les valeurs avant de les renvoyer, comme le " +"``on_change``." + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.Mapper.finalize:6 +msgid "source map_record" +msgstr "map_record source" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.Mapper.finalize:8 +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.Mapper.finalize:9 +msgid "mapped values" +msgstr "valeurs mappées" + +#. module: connector +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.Mapper.map_methods:1 +msgid "Yield all the methods decorated with ``@mapping``" +msgstr "Émets toutes les méthodes décorées avec ``@mapping``" + +#. module: connector +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.Mapper.map_record:1 +msgid "" +"Get a :py:class:`MapRecord` with record, ready to be converted using the " +"current Mapper." +msgstr "" +"Récupère un :py:class:`MapRecord` avec enregistrement, prêt à être converti " +"avec le Mappeur en cours." + +#. module: connector +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.Mapper.map_record:4 +msgid "record to transform" +msgstr "enregistrement à transformer" + +#. module: connector +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.Mapper.map_record:5 +msgid "optional parent record, for items" +msgstr "enregistrement parent optionnel, pour les items" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.Mapper.options:1 +msgid "Options can be accessed in the mapping methods with ``self.options``." +msgstr "" +"Des options peuvent être accédées dans les méthodes de mapping avec " +"``self.options``." + +#. module: connector +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.MappingDefinition:1 +msgid "Bases: :class:`tuple`" +msgstr "Bases : :class:`tuple`" + +#. module: connector +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.MappingDefinition.changed_by:1 +msgid "Alias for field number 0" +msgstr "Alias pour le champ numéro 0" + +#. module: connector +#: ../../../unit/mapper.pydocstring of +#: connector.unit.mapper.MappingDefinition.only_create:1 +msgid "Alias for field number 1" +msgstr "Alias pour le champs numéro 1" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.MetaMapper:1 +msgid "Bases: :class:`connector.connector.MetaConnectorUnit`" +msgstr "Bases : :class:`connector.connector.MetaConnectorUnit`" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.MetaMapper:1 +msgid "Metaclass for Mapper" +msgstr "Metaclass pour Mappeur" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.MetaMapper:3 +msgid "" +"Build a ``_map_methods`` dict of mappings methods. The keys of the dict are " +"the method names. The values of the dict are a namedtuple containing:" +msgstr "" +"construit un dict ``_map_methods`` des méthodes de mapping. Les clés de ce " +"dict sont les noms de méthode. Les valeurs sont des `namedtuple` contenant :" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.backend_to_m2o:1 +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.convert:1 +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.m2o_to_backend:1 +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.none:1 +msgid "A modifier intended to be used on the ``direct`` mappings." +msgstr "Un modificateur destiné à être utilisé sur les mapping ``directs``" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.backend_to_m2o:3 +msgid "" +"For a field from a backend which is an ID, search the corresponding binding " +"in Odoo and returns its ID." +msgstr "" +"Pour un champ d'un backend qui est un ID, recherche le binding correspondant" +" dans Odoo et renvoie son ID." + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.backend_to_m2o:6 +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.m2o_to_backend:5 +msgid "" +"When the field's relation is not a binding (i.e. it does not point to " +"something like ``magento.*``), the binding model needs to be provided in the" +" ``binding`` keyword argument." +msgstr "" +"Quand la relation du champ n'est pas un binding (càd ne pointe pas vers " +"quelque chose comme ``magento.*``), le modèle de liaison doit être fourni " +"avec l'argument nommé ``binding``." + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.backend_to_m2o:16 +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.convert:9 +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.m2o_to_backend:15 +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.none:11 +msgid "name of the source field in the record" +msgstr "nom du champ source dans l'enregistrement" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.backend_to_m2o:17 +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.m2o_to_backend:16 +msgid "name of the binding model is the relation is not a binding" +msgstr "nom du modèle de liaison si la relation n'est pas une liaison" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.backend_to_m2o:18 +msgid "include the inactive records in Odoo in the search" +msgstr "inclut les enregistrements inactifs d'Odoo dans la recherche" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.changed_by:1 +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.only_create:1 +msgid "Decorator for the mapping methods (:py:func:`mapping`)" +msgstr "Décorateur pour les méthodes de mapping (:py:func:`mapping`)" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.changed_by:3 +msgid "" +"When fields are modified in Odoo, we want to export only the modified " +"fields. Using this decorator, we can specify which fields updates should " +"trigger which mapping method." +msgstr "" +"Lorsque des champs sont modifié dans Odoo, nous ne devrions exporter que " +"les champs modifiés. En utilisant ce décorateur, nous pouvons préciser " +"quelles modifications de champs doivent déclencher quelle méthode de " +"mapping." + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.changed_by:7 +msgid "If ``changed_by`` is empty, the mapping is always active." +msgstr "Si ``changed_by`` est vide, le mapping est toujours actif." + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.changed_by:9 +msgid "" +"As far as possible, this decorator should be used for the exports, thus, " +"when we do an update on only a small number of fields on a record, the size " +"of the output record will be limited to only the fields really having to be " +"exported." +msgstr "" +"Autant que possible, ce décorateur devrait être utilisé pour les exports. De" +" cette façon lorsqu'on fait une modification sur une petite partie des " +"champs d'un enregistrement, la taille de l'enregistrement en sortie sera " +"limitée aux seuls champs devant être exportés." + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.changed_by:21 +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.changed_by:21 +msgid "field names which trigger the mapping when modified" +msgstr "noms de champs qui déclenchent le mapping à la modification" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.convert:3 +msgid "Convert a field's value to a given type." +msgstr "Convertit une valeur de champ vers un type donné" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.convert:10 +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.none:12 +msgid "True if the relation is a binding record" +msgstr "True si la relation est un enregistrement de binding" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.m2o_to_backend:3 +msgid "For a many2one, get the ID on the backend and returns it." +msgstr "Pour un many2one, récupère l'ID depuis le backend et le renvoie." + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.mapping:1 +msgid "Declare that a method is a mapping method." +msgstr "Déclare qu'une méthode est une méthode de mapping." + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.mapping:3 +msgid "It is then used by the :py:class:`Mapper` to convert the records." +msgstr "" +"C'est ensuite utilisé par le :py:class:`Mapper` pour convertir les " +"enregistrements." + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.none:3 +msgid "" +"Replace the False-ish values by None. It can be used in a pipeline of " +"modifiers when ." +msgstr "" +"Remplace les valeurs similaires à False par None. Ceci peut être utilisé " +"dans un enchaînement de modificateurs quand ." + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.only_create:3 +msgid "" +"A mapping decorated with ``only_create`` means that it has to be used only " +"for the creation of the records." +msgstr "" +"Un mapping décoré avec ``only_create`` indique qu'il doit être utilisé " +"uniquement pour a création d'enregistrements." + +#. module: connector +#: ../../api/api_queue.rst:3 ../../api/api_queue.rst:25 +msgid "Queue" +msgstr "Queue" + +#. module: connector +#: ../../api/api_queue.rst:7 +msgid "Job" +msgstr "Job" + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.Job:1 +msgid "A Job is a task to execute." +msgstr "Un job est une tâche à exécuter." + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.Job:5 +msgid "Id (UUID) of the job." +msgstr "Id (UUID) du job." + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.Job:9 +msgid "When the job is enqueued, UUID of the worker." +msgstr "Quand le job est placé dans la queue, UUID du worker." + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.Job:13 +msgid "" +"State of the job, can pending, enqueued, started, done or failed. The start " +"state is pending and the final state is done." +msgstr "" +"État du job, peut être en attente, en queue, démarré, terminé, échoué. " +"L'état initial est `en attente` et l'état final est `terminé`." + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.Job:18 +msgid "" +"The current try, starts at 0 and each time the job is executed, it increases" +" by 1." +msgstr "" +"L'essai actuel, démarre à 0 et s'incrémente de 1 chaque fois que le job est " +"exécuté." + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.Job:23 +msgid "" +"The maximum number of retries allowed before the job is considered as " +"failed." +msgstr "" +"Le nombre maximum d'essais permis avant que le job soit considéré comme " +"échoué." + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.Job:28 +msgid "Name of the function (in the form module.function_name)." +msgstr "Nom de la fonction (sous la forme module.nom_fonction)." + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.Job:32 +msgid "Arguments passed to the function when executed." +msgstr "Arguments transmis à la fonction pendant l'exécution." + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.Job:36 +msgid "Keyword arguments passed to the function when executed." +msgstr "Arguments nommés transmis à la fonction pendant l'exécution." + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.Job:40 +msgid "" +"Full string representing the function to be executed, ie. " +"module.function(args, kwargs)" +msgstr "" +"Chaîne complète représentant la fonction à exécuter, càd " +"module.fonction(args, kwargs)" + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.Job:45 +msgid "Human description of the job." +msgstr "Description du job à destination des utilisateurs." + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.Job:49 +msgid "The python function itself." +msgstr "La fonction Python elle-même." + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.Job:53 +msgid "Odoo model on which the job will run." +msgstr "Modèle Odoo pour lequel le job va fonctionner." + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.Job:57 +msgid "Priority of the job, 0 being the higher priority." +msgstr "Priorité du job, 0 étant la plus haute priorité." + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.Job:61 +msgid "Date and time when the job was created." +msgstr "Date et heure de création du job." + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.Job:65 +msgid "Date and time when the job was enqueued." +msgstr "Date et heure de mise en queue du job." + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.Job:69 +msgid "Date and time when the job was started." +msgstr "Date et heure de démarrage du job." + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.Job:73 +msgid "Date and time when the job was done." +msgstr "Date et heure d'arrêt du job." + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.Job:77 +msgid "A description of the result (for humans)." +msgstr "Une description du résultat (à destination des utilisateurs)." + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.Job:81 +msgid "Exception information (traceback) when the job failed." +msgstr "" +"Informations sur l'`Exception` (`traceback') ayant causé l'échec du job" + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.Job:85 +msgid "Odoo user id which created the job" +msgstr "Id de l'utilisateur Odoo qui a créé le job" + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.Job:89 +msgid "" +"Estimated Time of Arrival of the job. It will not be executed before this " +"date/time." +msgstr "" +"Heure estimée de lancement (ETA) du job. Il ne sera pas exécuté avant cette " +"date/heure." + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.Job:94 +msgid "True if the job has been canceled." +msgstr "True si le job a été annulé." + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.Job.perform:1 +msgid "Execute the job." +msgstr "Exécute le job." + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.Job.perform:3 +msgid "The job is executed with the user which has initiated it." +msgstr "Le job est exécuté avec l'utilisateur qui l'a initié." + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.Job.perform:5 +msgid "session to execute the job" +msgstr "session d'exécution du job" + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.Job.postpone:1 +msgid "" +"Write an estimated time arrival to n seconds later than now. Used when an " +"retryable exception want to retry a job later." +msgstr "" +"Écrit un heure estimée de lancement dans `n` secondes. Utilisé quand une " +"`Exception` non fatale souhaite relancer un job." + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.Job.uuid:1 +msgid "Job ID, this is an UUID" +msgstr "Id du job, c'est un UUID" + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.JobStorage:1 +msgid "Interface for the storage of jobs" +msgstr "Interface pour le stockage des jobs" + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.JobStorage.exists:1 +#: ../../../queue/job.pydocstring of +#: connector.queue.job.OdooJobStorage.exists:1 +msgid "Returns if a job still exists in the storage." +msgstr "Indique si un job existe encore dans l'espace de stockage." + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.JobStorage.load:1 +msgid "Read the job's data from the storage" +msgstr "Lit les donnés du job dans l'espace de stockage" + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.JobStorage.store:1 +msgid "Store a job" +msgstr "Stocke un job" + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.OdooJobStorage:1 +msgid "Bases: :class:`connector.queue.job.JobStorage`" +msgstr "Bases : :class:`connector.queue.job.JobStorage`" + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.OdooJobStorage:1 +msgid "Store a job on Odoo" +msgstr "Stocke un job dans Odoo" + +#. module: connector +#: ../../../queue/job.pydocstring of +#: connector.queue.job.OdooJobStorage.enqueue:1 +#: ../../../queue/job.pydocstring of +#: connector.queue.job.OdooJobStorage.enqueue_resolve_args:1 +msgid "Create a Job and enqueue it in the queue. Return the job uuid." +msgstr "Crée un job et le met en queue. Renvoie le UUID du job." + +#. module: connector +#: ../../../queue/job.pydocstring of +#: connector.queue.job.OdooJobStorage.enqueue:3 +msgid "" +"This expects the arguments specific to the job to be already extracted from " +"the ones to pass to the job function." +msgstr "" +"S'attend à ce que les arguments spécifiques au job soient déjà extraites de " +"ceux à passer à la fonction du job." + +#. module: connector +#: ../../../queue/job.pydocstring of +#: connector.queue.job.OdooJobStorage.load:1 +msgid "Read a job from the Database" +msgstr "Lit un job depuis la base de données" + +#. module: connector +#: ../../../queue/job.pydocstring of +#: connector.queue.job.OdooJobStorage.store:1 +msgid "Store the Job" +msgstr "Stocke le job" + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.job:1 +msgid "Decorator for jobs." +msgstr "Décorateur pour les jobs." + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.job:3 +msgid "Add a ``delay`` attribute on the decorated function." +msgstr "Ajoute un attribut ``delay`` sur la fonction décorée." + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.job:5 +msgid "" +"When ``delay`` is called, the function is transformed to a job and stored in" +" the Odoo queue.job model. The arguments and keyword arguments given in " +"``delay`` will be the arguments used by the decorated function when it is " +"executed." +msgstr "" +"Quand ``delay`` est appelée, la fonction est transformée en job et stockée " +"dans le modèle Odoo queue.job. Les arguments positionnels et nommés " +"transmis à ``delay`` seront les arguments utilisés par la fonction décorée " +"lorsqu'elle sera exécutée." + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.job:10 +msgid "The ``delay()`` function of a job takes the following arguments:" +msgstr "La fonction ``delay()`` d'un job reçoit les arguments suivants :" + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.job:13 +msgid "Current :py:class:`~odoo.addons.connector.session.ConnectorSession`" +msgstr "" +":py:class:`~odoo.addons.connector.session.ConnectorSession` en cours" + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.job:16 +msgid "name of the model on which the job has something to do" +msgstr "nom du modèle sur lequel le job a quelque chose à faire" + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.job:57 +msgid "*args and **kargs" +msgstr "*args et **kargs" + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.job:19 +msgid "" +"Arguments and keyword arguments which will be given to the called function " +"once the job is executed. They should be ``pickle-able``." +msgstr "" +"Arguments positionnels et nommés qui seront transmis à la fonction une fois " +"que le job est exécuté. Ils doivent être « pickle-able »." + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.job:22 +msgid "There is 4 special and reserved keyword arguments that you can use:" +msgstr "" +"Il existe 4 arguments nommés spéciaux et réservés que vous pouvez utiliser :" + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.job:24 +msgid "priority: priority of the job, the smaller is the higher priority." +msgstr "priority : priorité du job, une valeur plus petite étant prioritaire." + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.job:25 +msgid "Default is 10." +msgstr "10 par défaut." + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.job:27 +msgid "max_retries: maximum number of retries before giving up and set" +msgstr "max_retries : nombre maximal d'essais avant d'abandonner et définir" + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.job:27 +msgid "" +"the job state to 'failed'. A value of 0 means infinite retries. Default is " +"5." +msgstr "" +"l'état du job à `échoué`. Une valeur de 0 signifie un nombre infini " +"d'essais. Par défaut la valeur est 5." + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.job:30 +msgid "eta: the job can be executed only after this datetime" +msgstr "eta : le job ne peut être exécuté qu'après cette `datetime`" + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.job:30 +msgid "(or now + timedelta if a timedelta or integer is given)" +msgstr "" +"(ou maintenant + `timedelta` si un `timedelta` ou un entier est fourni)" + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.job:35 +msgid "description : a human description of the job," +msgstr "description : une description à destination des utilisateurs," + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.job:33 +msgid "intended to discriminate job instances (Default is the func.__doc__ or" +msgstr "" +"destinée à différencier les instances de job (Par défaut func.__doc__ ou" + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.job:35 +msgid "'Function %s' % func.__name__)" +msgstr "'Function %s' % func.__name__)" + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.job:37 +msgid "Example:" +msgstr "Exemple :" + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.job:57 +msgid "" +"See also: :py:func:`related_action` a related action can be attached to a " +"job" +msgstr "" +"Voir aussi : :py:func:`related_action` une action connexe peut être attachée" +" à un job" + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.related_action:1 +msgid "Attach a *Related Action* to a job." +msgstr "Attache une *action connexe* à un job" + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.related_action:3 +msgid "" +"A *Related Action* will appear as a button on the Odoo view. The button " +"will execute the action, usually it will open the form view of the record " +"related to the job." +msgstr "" +"Un *action connexe* apparaîtra comme un bouton dans la vue Odoo. Le " +"bouton exécutera l'action, habituellement une ouverture de formulaire de " +"l'enregistrement lié au job." + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.related_action:7 +msgid "The ``action`` must be a callable that responds to arguments::" +msgstr "" +"L'``action`` doit être un objet `callable` qui prends les arguments ::" + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.related_action:11 +msgid "Example usage:" +msgstr "Exemple d'utilisation :" + +#. module: connector +#: ../../../queue/job.pydocstring of connector.queue.job.related_action:34 +msgid "The kwargs are transmitted to the action:" +msgstr "Les ``kwargs`` sont transmis à l'action :" + +#. module: connector +#: ../../api/api_queue.rst:16 ../../../queue/model.pydocstring of +#: connector.queue.model.QueueWorker:1 +msgid "Worker" +msgstr "Worker" + +#. module: connector +#: ../../../queue/worker.pydocstring of connector.queue.worker.Worker:1 +#: ../../../queue/worker.pydocstring of connector.queue.worker.WorkerWatcher:1 +msgid "Bases: :class:`threading.Thread`" +msgstr "Bases : :class:`threading.Thread`" + +#. module: connector +#: ../../../queue/worker.pydocstring of connector.queue.worker.Worker:1 +msgid "Post and retrieve jobs from the queue, execute them" +msgstr "Poste et récupère des jobs de la queue, les exécute" + +#. module: connector +#: ../../../queue/worker.pydocstring of +#: connector.queue.worker.Worker.enqueue_job_uuid:1 +msgid "Enqueue a job:" +msgstr "Met un job en queue :" + +#. module: connector +#: ../../../queue/worker.pydocstring of +#: connector.queue.worker.Worker.enqueue_job_uuid:3 +msgid "" +"It will be executed by the worker as soon as possible (according to the " +"job's priority" +msgstr "" +"Il sera exécuté par le worker aussi tôt que possible (en fonction de la " +"priorité du job)" + +#. module: connector +#: ../../../queue/worker.pydocstring of connector.queue.worker.Worker.run:1 +msgid "Worker's main loop" +msgstr "Boucle principale du worker" + +#. module: connector +#: ../../../queue/worker.pydocstring of connector.queue.worker.Worker.run:3 +msgid "" +"Check if it still exists in the ``watcher``. When it does no longer exist, " +"it break the loop so the thread stops properly." +msgstr "" +"Vérifie s'il existe encore dans le ``watcher``. Quand il n'existe plus, il " +"sort de la boucle de façon que le `thread` s'arrête proprement." + +#. module: connector +#: ../../../queue/worker.pydocstring of connector.queue.worker.Worker.run:6 +msgid "Wait for jobs and execute them sequentially." +msgstr "Attend les jobs et les exécute séquentiellement." + +#. module: connector +#: ../../../queue/worker.pydocstring of +#: connector.queue.worker.Worker.run_job:1 +msgid "Execute a job" +msgstr "Exécute un job" + +#. module: connector +#: ../../../queue/worker.pydocstring of connector.queue.worker.WorkerWatcher:1 +msgid "Keep a sight on the workers and signal their aliveness." +msgstr "Garde un œil sur les workers et signale leur changement d'état." + +#. module: connector +#: ../../../queue/worker.pydocstring of connector.queue.worker.WorkerWatcher:3 +msgid "" +"A `WorkerWatcher` is shared between databases, so only 1 instance is " +"necessary to check the aliveness of the workers for every database." +msgstr "" +"Un `WorkerWatcher` est partagé entre plusieurs bases de données, donc seule " +"une instance est nécessaire pour vérifier l'état des workers pour chaque " +"base de données." + +#. module: connector +#: ../../../queue/worker.pydocstring of +#: connector.queue.worker.WorkerWatcher.available_db_names:1 +msgid "" +"Returns the databases for the server having the connector module installed." +msgstr "" +"Renvoie les bases de données du serveur où le module `connector` est " +"installé" + +#. module: connector +#: ../../../queue/worker.pydocstring of +#: connector.queue.worker.WorkerWatcher.available_db_names:4 +msgid "Available means that they can be used by a `Worker`." +msgstr "Disponible signifie qu'elles peuvent être utilisées par un `Worker`." + +#. module: connector +#: ../../../queue/worker.pydocstring of +#: connector.queue.worker.WorkerWatcher.available_db_names:6 +msgid "database names" +msgstr "Noms des bases de données" + +#. module: connector +#: ../../../queue/worker.pydocstring of +#: connector.queue.worker.WorkerWatcher.check_alive:1 +msgid "" +"Check if the the worker is still alive and notify its aliveness. Check if " +"the other workers are still alive, if they are dead, remove them from the " +"worker's pool." +msgstr "" +"Vérifie si le worker est toujours vivant et signale son état. Vérifie si les" +" autres workers sont toujours vivants, et si ce n'est pas le cas, les retire" +" du pool de workers." + +#. module: connector +#: ../../../queue/worker.pydocstring of +#: connector.queue.worker.WorkerWatcher.run:1 +msgid "`WorkerWatcher`'s main loop" +msgstr "boucle principale du `WorkerWatcher`" + +#. module: connector +#: ../../../queue/worker.pydocstring of +#: connector.queue.worker.WorkerWatcher.worker_lost:1 +msgid "Indicate if a worker is no longer referenced by the watcher." +msgstr "Indique si un worker n'est plus référencé par l'observateur." + +#. module: connector +#: ../../../queue/worker.pydocstring of +#: connector.queue.worker.WorkerWatcher.worker_lost:3 +msgid "Used by the worker threads to know if they have to exit." +msgstr "" +"Utilisé par les `threads` de worker pour savoir s'ils doivent s'arrêter." + +#. module: connector +#: ../../../queue/worker.pydocstring of connector.queue.worker.start_service:1 +msgid "Start the watcher" +msgstr "Démarre l'observateur" + +#. module: connector +#: ../../../queue/queue.pydocstring of connector.queue.queue.JobsQueue:1 +msgid "Holds the jobs planned for execution in memory." +msgstr "Contient en mémoire les jobs dont l'exécution est planifiée." + +#. module: connector +#: ../../../queue/queue.pydocstring of connector.queue.queue.JobsQueue:3 +msgid "" +"The Jobs are sorted, the higher the priority is, the earlier the jobs are " +"dequeued." +msgstr "" +"Les jobs sont triés, plus la priorité est importante, plus tôt les jobs sont" +" dépilés de la queue." + +#. module: connector +#: ../../../queue/queue.pydocstring of +#: connector.queue.queue.JobsQueue.dequeue:1 +msgid "Take the first job according to its priority and return it" +msgstr "Dépile et renvoie le premier job en fonction de sa priorité" + +#. module: connector +#: ../../api/api_queue.rst:34 +msgid "Models" +msgstr "Modèles" + +#. module: connector +#: ../../../queue/model.pydocstring of connector.queue.model.QueueJob:1 +#: ../../../queue/model.pydocstring of connector.queue.model.QueueWorker:1 +msgid "Bases: :class:`odoo.models.Model`" +msgstr "Bases : :class:`odoo.models.Model`" + +#. module: connector +#: ../../../queue/model.pydocstring of connector.queue.model.QueueJob:1 +msgid "Job status and result" +msgstr "État du job et résultat" + +#. module: connector +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueJob.autovacuum:1 +msgid "" +"Delete all jobs (active or not) done since more than ``_removal_interval`` " +"days." +msgstr "" +"Efface tous les jobs (actifs ou non) qui sont terminés depuis plus de " +"``_removal_interval`` jours." + +#. module: connector +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueJob.autovacuum:4 +msgid "Called from a cron." +msgstr "Appelé depuis une tâche planifiée (`cron`)." + +#. module: connector +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueJob.company_id:1 +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueJob.user_id:1 ../../../queue/model.pydocstring +#: of connector.queue.model.QueueJob.worker_id:1 +msgid "" +"The value of such a field is a recordset of size 0 (no record) or 1 (a " +"single record)." +msgstr "" +"La valeur d'un tel champ est un `recordset` de taille 0 (pas " +"d'enregistrement) ou 1 (enregistrement unique)." + +#. module: connector +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueJob.company_id:4 +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueJob.user_id:4 ../../../queue/model.pydocstring +#: of connector.queue.model.QueueJob.worker_id:4 +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueWorker.job_ids:5 +#: ../../../queue/model.pydocstring of +#: connector.queue.model.RequeueJob.job_ids:3 +msgid "name of the target model (string)" +msgstr "nom du modèle cible (chaîne de caractères)" + +#. module: connector +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueJob.company_id:6 +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueJob.user_id:6 ../../../queue/model.pydocstring +#: of connector.queue.model.QueueJob.worker_id:6 +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueWorker.job_ids:10 +#: ../../../queue/model.pydocstring of +#: connector.queue.model.RequeueJob.job_ids:21 +msgid "" +"an optional domain to set on candidate values on the client side (domain or " +"string)" +msgstr "" +"un `domain` optionnel à définir sur les valeurs candidates côté client " +"(`domain` ou `string`)" + +#. module: connector +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueJob.company_id:9 +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueJob.user_id:9 ../../../queue/model.pydocstring +#: of connector.queue.model.QueueJob.worker_id:9 +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueWorker.job_ids:13 +#: ../../../queue/model.pydocstring of +#: connector.queue.model.RequeueJob.job_ids:24 +msgid "" +"an optional context to use on the client side when handling that field " +"(dictionary)" +msgstr "" +"un `context` optionnel à utiliser côté client à la prise en charge de ce " +"champ (dictionnaire)" + +#. module: connector +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueJob.company_id:12 +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueJob.user_id:12 ../../../queue/model.pydocstring +#: of connector.queue.model.QueueJob.worker_id:12 +msgid "" +"what to do when the referred record is deleted; possible values are: ``'set " +"null'``, ``'restrict'``, ``'cascade'``" +msgstr "" +"quoi faire quand l'enregistrement en rapport est effacé ; les valeurs " +"possibles sont : ``'set null'``, ``'restrict'``, ``'cascade'``" + +#. module: connector +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueJob.company_id:15 +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueJob.user_id:15 ../../../queue/model.pydocstring +#: of connector.queue.model.QueueJob.worker_id:15 +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueWorker.job_ids:16 +msgid "" +"whether JOINs are generated upon search through that field (boolean, by " +"default ``False``)" +msgstr "" +"si les JOINs sont générés lors de la recherche sur ce champ (booleen, par " +"défaut ``False``)" + +#. module: connector +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueJob.company_id:18 +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueJob.user_id:18 ../../../queue/model.pydocstring +#: of connector.queue.model.QueueJob.worker_id:18 +msgid "" +"set it to ``True`` to make fields of the target model accessible from the " +"current model (corresponds to ``_inherits``)" +msgstr "" +"définir à ``True`` pour rendre les champs du modèle cible accessibles depuis" +" le modèle en cours (correspond à ``_inherits``)" + +#. module: connector +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueJob.company_id:21 +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueJob.user_id:21 ../../../queue/model.pydocstring +#: of connector.queue.model.QueueJob.worker_id:21 +#: ../../../queue/model.pydocstring of +#: connector.queue.model.RequeueJob.job_ids:5 +msgid "" +"The attribute `comodel_name` is mandatory except in the case of related " +"fields or field extensions." +msgstr "" +"L'attribut `comodel_name` est obligatoire sauf dans le cas des champs " +"`related` ou des extensions de champs." + +#. module: connector +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueJob.exc_info:1 ../../../queue/model.pydocstring +#: of connector.queue.model.QueueJob.result:1 +msgid "" +"Very similar to :class:`~.Char` but used for longer contents, does not have " +"a size and usually displayed as a multiline text box." +msgstr "" +"Très similaire à :class:`~.Char` mais utilisé pour des contenus plus longs, " +"sans taille spécifiée et généralement affiché dans une boite de texte multi-" +"lignes." + +#. module: connector +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueJob.exc_info:4 ../../../queue/model.pydocstring +#: of connector.queue.model.QueueJob.result:4 +msgid "whether the value of this field can be translated" +msgstr "si la valeur de ce champ peut être traduite ou non" + +#. module: connector +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueJob.open_related_action:1 +msgid "Open the related action associated to the job" +msgstr "Ouvre l'action associée au job" + +#. module: connector +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueWorker.assign_jobs:1 +msgid "Assign ``n`` jobs to the worker of the current process" +msgstr "Affecte ``n`` jobs au worker du processus en cours" + +#. module: connector +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueWorker.assign_jobs:3 +msgid "``n`` is ``max_jobs`` or unlimited if ``max_jobs`` is None" +msgstr "``n`` est ``max_jobs`` ou illimité si ``max_jobs`` est None" + +#. module: connector +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueWorker.assign_jobs:5 +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueWorker.assign_then_enqueue:11 +msgid "maximal limit of jobs to assign on a worker" +msgstr "nombre maximal de jobs à affecter à un worker" + +#. module: connector +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueWorker.assign_then_enqueue:1 +msgid "" +"Assign all the jobs not already assigned to a worker. Then enqueue all the " +"jobs having a worker but not enqueued." +msgstr "" +"Affecte tous les jobs non encore affectés à un worker. Puis met en queue " +"tous les jobs qui ont un worker mais qui ne sont pas dans la queue." + +#. module: connector +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueWorker.assign_then_enqueue:4 +msgid "Each operation is atomic." +msgstr "Chaque opération est atomique." + +#. module: connector +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueWorker.assign_then_enqueue:6 +msgid "" +"commit transaction ``cr.commit()`` is called, so please always call this " +"method in your own transaction, not in the main Odoo's transaction" +msgstr "" +"valide la transaction. ``cr.commit()`` est appelé, donc veuillez appeler " +"cette méthode dans vos propres transactions, pas dans la transaction " +"principale d'Odoo" + +#. module: connector +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueWorker.enqueue_jobs:1 +msgid "Enqueue all the jobs assigned to the worker of the current process" +msgstr "Met en queue tous les jobs affectés au worker du processus en cours" + +#. module: connector +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueWorker.job_ids:1 +msgid "" +"One2many field; the value of such a field is the recordset of all the " +"records in `comodel_name` such that the field `inverse_name` is equal to the" +" current record." +msgstr "" +"Champ one2many ; la valeur d'un tel champ est le `recordset` de tous les " +"enregistrements dans `comodel_name` de sorte que le champ `inverse_name` " +"soit égal à l'enregistrement actuel." + +#. module: connector +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueWorker.job_ids:7 +msgid "name of the inverse `Many2one` field in `comodel_name` (string)" +msgstr "nom du champ `many2one` réciproque côté `comodel_name` (string)" + +#. module: connector +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueWorker.job_ids:19 +#: ../../../queue/model.pydocstring of +#: connector.queue.model.RequeueJob.job_ids:27 +msgid "optional limit to use upon read (integer)" +msgstr "limite optionnelle à utiliser à la lecture (entier)" + +#. module: connector +#: ../../../queue/model.pydocstring of +#: connector.queue.model.QueueWorker.job_ids:21 +msgid "" +"The attributes `comodel_name` and `inverse_name` are mandatory except in the" +" case of related fields or field extensions." +msgstr "" +"Les attributs `comodel_name` et `inverse_name` sont obligatoires sauf dans " +"les cas des champs `related` ou des extensions de champs." + +#. module: connector +#: ../../../queue/model.pydocstring of connector.queue.model.RequeueJob:1 +msgid "Bases: :class:`odoo.models.TransientModel`" +msgstr "Bases : :class:`odoo.models.TransientModel`" + +#. module: connector +#: ../../../queue/model.pydocstring of +#: connector.queue.model.RequeueJob.job_ids:1 +msgid "Many2many field; the value of such a field is the recordset." +msgstr "Champ many2many ; la valeur d'un tel champ est un `recordset`." + +#. module: connector +#: ../../../queue/model.pydocstring of +#: connector.queue.model.RequeueJob.job_ids:8 +msgid "" +"optional name of the table that stores the relation in the database (string)" +msgstr "" +"nom optionnel de la table qui stocke la relation dans la base de données " +"(string)" + +#. module: connector +#: ../../../queue/model.pydocstring of +#: connector.queue.model.RequeueJob.job_ids:11 +msgid "" +"optional name of the column referring to \"these\" records in the table " +"`relation` (string)" +msgstr "" +"nom optionnel de la colonne qui se réfère à \"ces\" enregistrements dans la " +"table `relation` (string)" + +#. module: connector +#: ../../../queue/model.pydocstring of +#: connector.queue.model.RequeueJob.job_ids:14 +msgid "" +"optional name of the column referring to \"those\" records in the table " +"`relation` (string)" +msgstr "" +"nom optionnel de la colonne qui se réfère à \"ces\" enregistrements dans la " +"table `relation` (string)" + +#. module: connector +#: ../../../queue/model.pydocstring of +#: connector.queue.model.RequeueJob.job_ids:17 +msgid "" +"The attributes `relation`, `column1` and `column2` are optional. If not " +"given, names are automatically generated from model names, provided " +"`model_name` and `comodel_name` are different!" +msgstr "" +"Les attributs `relation`, `column1` et `column2` sont optionnels. S'ils ne " +"sont pas fournis, des noms sont générés automatiquement depuis les noms de " +"modèles, à condition que `model_name` et `comodel_name` soient differents !" + +#. module: connector +#: ../../api/api_session.rst:2 +msgid "Session" +msgstr "Session" + +#. module: connector +#: ../../../session.pydocstring of connector.session.ConnectorSession:1 +msgid "Container for the Odoo transactional stuff:" +msgstr "Conteneur pour les choses transactionnelles d'Odoo :" + +#. module: connector +#: ../../../session.pydocstring of connector.session.ConnectorSession:5 +msgid "The Environment" +msgstr "L'Environnement" + +#. module: connector +#: ../../../session.pydocstring of connector.session.ConnectorSession:9 +msgid "The Odoo Cursor" +msgstr "Le curseur d'Odoo" + +#. module: connector +#: ../../../session.pydocstring of connector.session.ConnectorSession:13 +#: ../../../session.pydocstring of +#: connector.session.ConnectorSessionHandler:10 +msgid "The User ID as integer" +msgstr "L'ID de l'utilisateur (entier)" + +#. module: connector +#: ../../../session.pydocstring of connector.session.ConnectorSession:17 +msgid "The registry of models" +msgstr "Le registre des modèles" + +#. module: connector +#: ../../../session.pydocstring of connector.session.ConnectorSession:21 +#: ../../../session.pydocstring of +#: connector.session.ConnectorSessionHandler:14 +msgid "The current Odoo's context" +msgstr "Le `context` actuel d'Odoo" + +#. module: connector +#: ../../../session.pydocstring of connector.session.ConnectorSession.browse:1 +msgid "Shortcut to :py:class:`odoo.models.BaseModel.browse`" +msgstr "Raccourci vers :py:class:`odoo.models.BaseModel.browse`" + +#. module: connector +#: ../../../session.pydocstring of +#: connector.session.ConnectorSession.change_context:1 +msgid "Context Manager: create a new Env with an updated context" +msgstr "`Context Manager` : crée un nouvel Env avec un `context` mis à jour" + +#. module: connector +#: ../../../session.pydocstring of +#: connector.session.ConnectorSession.change_context:3 +msgid "" +"It generates a new :class:`odoo.api.Environment` used within the context " +"manager, where the context is extended with the arguments. The original " +"environment is restored at the closing of the context manager." +msgstr "" +"Génère un nouvel :class:`odoo.api.Environment` utilisé à l'intérieur du " +"`context manager`, où le `context` est enrichi avec les arguments. " +"L'environnement original est restauré à la fermeture du `context manager`." + +#. module: connector +#: ../../../session.pydocstring of +#: connector.session.ConnectorSession.change_context:8 +msgid "" +"The extended context is either the provided ``context`` in which " +"``overrides`` are merged or the *current* context in which ``overrides`` are" +" merged e.g." +msgstr "" +"Le `context` enrichi est soit le ``context`` fourni, dans lequel les " +"``overrides`` sont fusionnés, ou le `context` *actuel* dans lequel les " +"``overrides`` sont fusionné, càd" + +#. module: connector +#: ../../../session.pydocstring of +#: connector.session.ConnectorSession.change_context:20 +#: ../../../session.pydocstring of +#: connector.session.ConnectorSession.change_user:8 +msgid "" +"only recordsets read within the context manager will be attached to this " +"environment. In many cases, you will prefer to use " +":meth:`odoo.models.BaseModel.with_context`" +msgstr "" +"seuls les `recordset` lus à l'intérieur du `context manager` seront attachés" +" à cet environnement. Dans beaucoup de cas, vous préférerez utiliser " +":meth:`odoo.models.BaseModel.with_context`" + +#. module: connector +#: ../../../session.pydocstring of +#: connector.session.ConnectorSession.change_user:1 +msgid "Context Manager: create a new Env with the specified user" +msgstr "`Context Manager` : crée un nouvel Env avec l'utilisateur spécifié" + +#. module: connector +#: ../../../session.pydocstring of +#: connector.session.ConnectorSession.change_user:3 +msgid "" +"It generates a new :class:`odoo.api.Environment` used within the context " +"manager, where the user is replaced by the specified one. The original " +"environment is restored at the closing of the context manager." +msgstr "" +"Ceci génère un nouvel :class:`odoo.api.Environment` utilisé à l'intérieur" +" du `context manager`, où l'utilisateur est remplacé par celui spécifié. " +"L'environnement original est restaré à la fermeture du `context manager`." + +#. module: connector +#: ../../../session.pydocstring of connector.session.ConnectorSession.close:1 +msgid "Close the cursor" +msgstr "Ferme le curseur" + +#. module: connector +#: ../../../session.pydocstring of connector.session.ConnectorSession.commit:1 +msgid "Commit the cursor" +msgstr "Valide la transaction" + +#. module: connector +#: ../../../session.pydocstring of connector.session.ConnectorSession.create:1 +msgid "Shortcut to :py:class:`odoo.models.BaseModel.create`" +msgstr "Raccourci pour :py:class:`odoo.models.BaseModel.create`" + +#. module: connector +#: ../../../session.pydocstring of +#: connector.session.ConnectorSession.is_module_installed:1 +msgid "" +"Indicates whether a module is installed or not on the current database." +msgstr "" +"Indique si un module est installé ou non dans la base de données en cours." + +#. module: connector +#: ../../../session.pydocstring of +#: connector.session.ConnectorSession.is_module_installed:4 +msgid "" +"Use a convention established for the connectors addons: To know if a module " +"is installed, it looks if an (abstract) model with name " +"``module_name.installed`` is loaded in the registry." +msgstr "" +"Utilise une convention établie pour les modules connecteurs : pour savoir si" +" un module est installé, il regarde si un modèle (abstrait) avec le nom " +"``nom_module.installed`` est chargé dans le registre." + +#. module: connector +#: ../../../session.pydocstring of connector.session.ConnectorSession.read:1 +msgid "Shortcut to :py:class:`odoo.models.BaseModel.read`" +msgstr "Raccourci pour :py:class:`odoo.models.BaseModel.read`" + +#. module: connector +#: ../../../session.pydocstring of +#: connector.session.ConnectorSession.rollback:1 +msgid "Rollback the cursor" +msgstr "Annule la transaction" + +#. module: connector +#: ../../../session.pydocstring of connector.session.ConnectorSession.search:1 +msgid "Shortcut to :py:class:`odoo.models.BaseModel.search`" +msgstr "Raccourci pour :py:class:`odoo.models.BaseModel.search`" + +#. module: connector +#: ../../../session.pydocstring of connector.session.ConnectorSession.write:1 +msgid "Shortcut to :py:class:`odoo.models.BaseModel.write`" +msgstr "Raccourci pour :py:class:`odoo.models.BaseModel.write`" + +#. module: connector +#: ../../../session.pydocstring of connector.session.ConnectorSessionHandler:1 +msgid "" +"Allow to create a new instance of " +":py:class:`~connector.session.ConnectorSession` for a database." +msgstr "" +"Permet de créer une nouvelle instance de " +":py:class:`~connector.session.ConnectorSession` pour une base de données." + +#. module: connector +#: ../../../session.pydocstring of connector.session.ConnectorSessionHandler:6 +msgid "The name of the database we're working on" +msgstr "Le nom de la base de données sur laquelle on travaille" + +#. module: connector +#: ../../../session.pydocstring of +#: connector.session.ConnectorSessionHandler.session:1 +msgid "" +"Context Manager: start a new session and ensure that the session's cursor " +"is:" +msgstr "" +"`Context Manager` : démarre une nouvelle session et s'assure que le curseur " +"de la session est :" + +#. module: connector +#: ../../../session.pydocstring of +#: connector.session.ConnectorSessionHandler.session:4 +msgid "rollbacked on errors" +msgstr "annulé en cas d'erreur" + +#. module: connector +#: ../../../session.pydocstring of +#: connector.session.ConnectorSessionHandler.session:5 +msgid "commited at the end of the ``with`` context when no error occured" +msgstr "validé à la fin du contexte ``with`` si aucune erreur n'est apparue" + +#. module: connector +#: ../../../session.pydocstring of +#: connector.session.ConnectorSessionHandler.session:6 +msgid "always closed at the end of the ``with`` context" +msgstr "toujours fermé à la fin d'un contexte ``with``" + +#. module: connector +#: ../../../session.pydocstring of +#: connector.session.ConnectorSessionHandler.session:7 +msgid "it handles the registry signaling" +msgstr "il gère le signalement du registre" + +#. module: connector +#: ../../api/api_synchronizer.rst:2 +msgid "Synchronizer" +msgstr "Synchroniseur" + +#. module: connector +#: ../../../unit/synchronizer.pydocstring of +#: connector.unit.synchronizer.Deleter:1 +#: ../../../unit/synchronizer.pydocstring of +#: connector.unit.synchronizer.Exporter:1 +#: ../../../unit/synchronizer.pydocstring of +#: connector.unit.synchronizer.Importer:1 +msgid "Bases: :class:`connector.unit.synchronizer.Synchronizer`" +msgstr "Bases : :class:`connector.unit.synchronizer.Synchronizer`" + +#. module: connector +#: ../../../unit/synchronizer.pydocstring of +#: connector.unit.synchronizer.Deleter:1 +msgid "Synchronizer for deleting a record on the backend" +msgstr "Synchroniseur pour effacer un enregistrement du backend" + +#. module: connector +#: ../../../unit/synchronizer.pydocstring of +#: connector.unit.synchronizer.Exporter:1 +msgid "Synchronizer for exporting data from Odoo to a backend" +msgstr "Synchroniseur pour exporter des donnés d'Odoo vers un backend" + +#. module: connector +#: ../../../unit/synchronizer.pydocstring of +#: connector.unit.synchronizer.Importer:1 +msgid "Synchronizer for importing data from a backend to Odoo" +msgstr "Synchroniseur pour importer des données d'un backend vers Odoo" + +#. module: connector +#: ../../../unit/synchronizer.pydocstring of +#: connector.unit.synchronizer.Synchronizer:1 +msgid "Base class for synchronizers" +msgstr "Classe de base des synchroniseurs" + +#. module: connector +#: ../../../unit/synchronizer.pydocstring of +#: connector.unit.synchronizer.Synchronizer.backend_adapter:1 +msgid "Return an instance of ``BackendAdapter`` for the synchronization." +msgstr "Renvoie une instance de ``BackendAdapter`` pour la synchronisation." + +#. module: connector +#: ../../../unit/synchronizer.pydocstring of +#: connector.unit.synchronizer.Synchronizer.backend_adapter:4 +#: ../../../unit/synchronizer.pydocstring of +#: connector.unit.synchronizer.Synchronizer.binder:3 +#: ../../../unit/synchronizer.pydocstring of +#: connector.unit.synchronizer.Synchronizer.mapper:3 +msgid "" +"The instanciation is delayed because some synchronisations do not need such " +"an unit and the unit may not exist." +msgstr "" +"L'instanciation est retardée parce que certaines synchronisations n'ont pas " +"besoin d'une telle unité et celle-ci peut ne pas exister." + +#. module: connector +#: ../../../unit/synchronizer.pydocstring of +#: connector.unit.synchronizer.Synchronizer.binder:1 +msgid "Return an instance of ``Binder`` for the synchronization." +msgstr "Renvoie une instance de liaison ``Binder`` pour la synchronisation." + +#. module: connector +#: ../../../unit/synchronizer.pydocstring of +#: connector.unit.synchronizer.Synchronizer.binder:6 +msgid ":py:class:`connector.unit.binder.Binder`" +msgstr ":py:class:`connector.unit.binder.Binder`" + +#. module: connector +#: ../../../unit/synchronizer.pydocstring of +#: connector.unit.synchronizer.Synchronizer.mapper:1 +msgid "Return an instance of ``Mapper`` for the synchronization." +msgstr "Renvoie une instance de mappeur ``Mapper`` pour la synchronisation" + +#. module: connector +#: ../../../unit/synchronizer.pydocstring of +#: connector.unit.synchronizer.Synchronizer.run:1 +msgid "Run the synchronization" +msgstr "Lance la synchronisation" + +#. module: connector +#: ../../../event.pydocstring of connector.event.Event:14 +msgid "Then to subscribe one or more consumers, an event has a function::" +msgstr "" +"Ensuite pour abonner un ou plusieurs consommateurs, un événement a une " +"fonction :" + +#. module: connector +#: ../../../exception.pydocstring of connector.exception.IDMissingInBackend:1 +msgid "The ID does not exist in the backend" +msgstr "L'ID n'existe pas dans le backend" + +#. module: connector +#: ../../../unit/mapper.pydocstring of connector.unit.mapper.MapChild:23 +msgid "" +"Possibly filter out some lines (can be done by inheriting " +":py:meth:`skip_item`)" +msgstr "" +"Éventuellement exclure certaines lignes (en surchargeant " +":py:meth:`skip_item`)" + +#. module: connector +#: ../../../event.pydocstring of connector.event.Event:30 +msgid "We can also replace a consumer::" +msgstr "On peut aussi remplacer un consommateur ::" + +#~ msgid "We can also replace an consumer::" +#~ msgstr "On peut aussi remplacer un consommateur ::" + +#~ msgid "int" +#~ msgstr "int" + +#~ msgid "dict" +#~ msgstr "dict" + +#~ msgid "MappingDefinition(changed_by, only_create)" +#~ msgstr "MappingDefinition(changed_by, only_create)" + +#~ msgid "list" +#~ msgstr "list" + +#~ msgid "The ID of does not exist in the backend" +#~ msgstr "L'ID " + +#~ msgid "Then to subscribe one or more consumers, a consumer is a function::" +#~ msgstr "" +#~ "Ensuite pour abonner un ou plusieurs consommateurs, un événement a une " +#~ "fonction ``subscribe`` ::" + +#~ msgid "We can also replace an event::" +#~ msgstr "On peut également remplacer un consommateur ::" diff --git a/connector/doc/locale/fr/LC_MESSAGES/guides.po b/connector/doc/locale/fr/LC_MESSAGES/guides.po new file mode 100644 index 000000000..54db36075 --- /dev/null +++ b/connector/doc/locale/fr/LC_MESSAGES/guides.po @@ -0,0 +1,1328 @@ +# +msgid "" +msgstr "" +"Project-Id-Version: Connector\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-04-15 22:28+0300\n" +"PO-Revision-Date: 2015-05-05 11:55+0100\n" +"Last-Translator: Guewen Baconnier \n" +"Language-Team: fr \n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 1.5.4\n" + +#. module: connector +#: ../../guides/bootstrap_connector.rst:6 +msgid "Boostrapping a connector" +msgstr "Amorcer la création un nouveau connecteur" + +#. module: connector +#: ../../guides/bootstrap_connector.rst:8 +msgid "We'll see the steps to bootstrap a new connector." +msgstr "" +"Nous allons voir les étapes pour amorcer la création d'un nouveau connecteur" + +#. module: connector +#: ../../guides/bootstrap_connector.rst:10 +msgid "" +"Besides that, you may want to use the existing connectors to have some real " +"implementation examples:" +msgstr "" +"À côté de ça, vous devriez utiliser les connecteurs existants pour avoir des " +"exemples réels d'implémentation:" + +#. module: connector +#: ../../guides/bootstrap_connector.rst:16 +msgid "" +"Some boilerplate is necessary, so this document will guide you through some " +"steps. Please also take a look on the :ref:`naming-convention`." +msgstr "" +"Du code boilerplate est nécessaire, donc ce document va vous guider à " +"travers différentes étapes. Consultez également les :ref:`naming-convention`." + +#. module: connector +#: ../../guides/bootstrap_connector.rst:59 +msgid "Nothing special but 2 things to note:" +msgstr "Il y a 2 points à noter :" + +#. module: connector +#: ../../guides/bootstrap_connector.rst:61 +msgid "It depends from ``connector``." +msgstr "Il dépend de ``connector``." + +#. module: connector +#: ../../guides/bootstrap_connector.rst:62 +msgid "The module category should be ``Connector``." +msgstr "La catégorie du module doit être ``Connector``." + +#. module: connector +#: ../../guides/bootstrap_connector.rst:64 +msgid "" +"Of course, we also need to create the ``__init__.py`` file where we will put " +"the imports of our python modules." +msgstr "" +"Bien sûr, nous devons aussi créer le fichier ``__init__.py`` où nous plaçons " +"les imports de nos modules Python." + +#. module: connector +#: ../../guides/bootstrap_connector.rst:70 +msgid "Install the module in the connector" +msgstr "Installation du module dans le connecteur" + +#. module: connector +#: ../../guides/bootstrap_connector.rst:72 +msgid "" +"Each new module needs to be plugged in the connector's framework. That's " +"just a matter of following a convention and creating ``connector_coffee/" +"connector.py``" +msgstr "" +"Chaque nouveau module doit être branché dans le framework du connecteur. " +"C'est juste un question de suivre une convention et créer un fichier " +"``connector_coffee/connector.py``" + +#. module: connector +#: ../../guides/bootstrap_connector.rst:82 +msgid "" +"If you miss this line of code, your ConnectorUnit classes won't be found." +msgstr "" +"Si vous oubliez cette ligne de code, vos classes ConnectorUnit seront " +"introuvables." + +#. module: connector +#: ../../guides/bootstrap_connector.rst:90 +msgid "" +"To prevent this, we use a little trick: create an abstract model and look in " +"the registry if it is loaded." +msgstr "" +"Pour éviter cela, nous utilisons une astuce: créer un « abstract model » et " +"regarder dans le registre s'il est chargé." + +#. module: connector +#: ../../guides/bootstrap_connector.rst:96 +msgid "Declare the backends" +msgstr "Déclaration des backends" + +#. module: connector +#: ../../guides/bootstrap_connector.rst:98 +msgid "Our module is compatible with the coffee machines:" +msgstr "Notre module est compatible avec les machines à café :" + +#. module: connector +#: ../../guides/bootstrap_connector.rst:100 +msgid "Coffee 1900" +msgstr "Coffee 1900" + +#. module: connector +#: ../../guides/bootstrap_connector.rst:101 +msgid "Coffee 2900" +msgstr "Coffee 2900" + +#. module: connector +#: ../../guides/bootstrap_connector.rst:103 +msgid "" +"So we'll declare a backend `coffee`, the generic entity, and a backend per " +"version." +msgstr "" +"Donc nous allons déclarer un backend `coffee`, l'entité générique, et un " +"backend différent par version." + +#. module: connector +#: ../../guides/bootstrap_connector.rst:106 +msgid "Put this in ``connector_coffee/backend.py``::" +msgstr "Placez ceci dans ``connector_coffee/backend.py``::" + +#. module: connector +#: ../../guides/bootstrap_connector.rst:118 +msgid "Backend Model" +msgstr "Modèle du backend" + +#. module: connector +#: ../../guides/bootstrap_connector.rst:120 +msgid "We declared the backends, but we need a model to configure them." +msgstr "" +"Nous avons déclaré les backends, mais nous avons besoin d'un modèle pour les " +"configurer." + +#. module: connector +#: ../../guides/bootstrap_connector.rst:122 +msgid "" +"We create a model ``coffee.backend`` which is an ``_inherit`` of ``connector." +"backend``. In ``connector_coffee/coffee_model.py``::" +msgstr "" +"Nous créons un modèle ``coffee.backend`` qui est un ``_inherit`` de " +"``connector.backend``. Dans ``connector_coffee/coffee_model.py``::" + +#. module: connector +#: ../../guides/bootstrap_connector.rst:157 +msgid "Notes:" +msgstr "Notes :" + +#. module: connector +#: ../../guides/bootstrap_connector.rst:159 +msgid "" +"The ``_backend_type`` must be the same than the name in the backend in " +"`Declare the backends`_." +msgstr "" +"Le ``_backend_type`` doit être le même que le nom du backend dans " +"`Déclaration des backends`_." + +#. module: connector +#: ../../guides/bootstrap_connector.rst:161 +msgid "" +"the versions should be the same than the ones declared in `Declare the " +"backends`_." +msgstr "" +"les versions doivent être les mêmes que celles déclarées dans `Déclaration " +"des backends`_." + +#. module: connector +#: ../../guides/bootstrap_connector.rst:162 +msgid "" +"We may want to add as many fields as we want to configure our connection or " +"configuration regarding the backend in that model." +msgstr "" +"Nous pouvons ajouter dans ce modèle autant de champs que nous voulons pour " +"configurer notre connexion ou configuration en rapport avec le backend." + +#. module: connector +#: ../../guides/bootstrap_connector.rst:168 +msgid "Abstract Binding" +msgstr "Binding abstrait" + +#. module: connector +#: ../../guides/bootstrap_connector.rst:170 +msgid "" +"If we have many :ref:`binding`, we may want to create an abstract model for " +"them." +msgstr "" +"Si nous avons de nombreux :ref:`binding`, nous pouvons créer un modèle " +"abstrait pour eux." + +#. module: connector +#: ../../guides/bootstrap_connector.rst:173 +msgid "It can be as follows (in ``connector_coffee/connector.py``)::" +msgstr "Cela peut être comme suit (dans ``connector_coffee/connector.py``)::" + +#. module: connector +#: ../../guides/bootstrap_connector.rst:197 ../../guides/concepts.rst:125 +msgid "Environment" +msgstr "Environnement" + +#. module: connector +#: ../../guides/bootstrap_connector.rst:199 +msgid "" +"We'll often need to create a new environment to work with. I propose to " +"create a helper method which build it for us (in ``connector_coffee/" +"connector.py``::" +msgstr "" +"Nous aurons souvent besoin de créer un nouvel environnement avec lequel " +"travailler. Je propose de créer une méthode auxiliaire qui le construit " +"(dans ``connector_coffee/connector.py``::" + +#. module: connector +#: ../../guides/bootstrap_connector.rst:218 +msgid "" +"Note that the part regarding the language definition is totally optional but " +"I left it as an example." +msgstr "" +"Remarquez que la partie qui concerne la définition du langage est " +"complètement optionnelle mais elle est conservée pour l'exemple." + +#. module: connector +#: ../../guides/bootstrap_connector.rst:239 +msgid "ConnectorUnit classes" +msgstr "Classes ConnectorUnit" + +#. module: connector +#: ../../guides/bootstrap_connector.rst:241 +msgid "" +"We'll probably need to create synchronizers, mappers, backend adapters, " +"binders and maybe our own types of ConnectorUnit classes." +msgstr "" +"Nous aurons probablement besoin de créer des synchroniseurs, des mappeurs, " +"des adaptateurs de backend, des bindings, et peut-être nos propres types de " +"classes ConnectorUnit" + +#. module: connector +#: ../../guides/code_overview.rst:5 +msgid "Code Overview" +msgstr "Survol du code" + +#. module: connector +#: ../../guides/code_overview.rst:7 +msgid "Here is an overview of some of the concepts in the framework." +msgstr "Voici un survol de certains concepts du framework." + +#. module: connector +#: ../../guides/code_overview.rst:9 +msgid "" +"As an example, we'll see the steps for exporting an invoice to Magento. The " +"steps won't show all the steps, but a simplified excerpt of a real use case " +"exposing the main ideas." +msgstr "" +"Comme exemple, nous allons voir les étapes pour exporter une facture vers " +"Magento. Ce n'est pas un exemple complet mais un aperçu d'un cas réel pour " +"exposer les idée principales." + +#. module: connector +#: ../../guides/code_overview.rst:15 +msgid "Backends" +msgstr "Backends" + +#. module: connector +#: ../../guides/code_overview.rst:17 +msgid "" +"All start with the declaration of the :py:class:`~connector.backend." +"Backend`::" +msgstr "" +"Tout commence par une déclaration du :py:class:`~connector.backend.Backend`::" + +#. module: connector +#: ../../guides/code_overview.rst:27 +msgid "" +"As you see, Magento is the parent of Magento 1.7. We can define a hierarchy " +"of backends." +msgstr "" +"Comme vous pouvez voir, Magento est parent de Magento 1.7. Nous pouvons donc " +"définir une hiérarchie de backends." + +#. module: connector +#: ../../guides/code_overview.rst:32 ../../guides/concepts.rst:213 +msgid "Bindings" +msgstr "Bindings (Liaisons)" + +#. module: connector +#: ../../guides/code_overview.rst:55 ../../guides/concepts.rst:88 +msgid "Session" +msgstr "Session" + +#. module: connector +#: ../../guides/code_overview.rst:57 +msgid "" +"The framework uses :py:class:`~connector.session.ConnectorSession` objects " +"to store the ``cr``, ``uid`` and ``context`` in a :class:`odoo.api." +"Environment`. So from a session, we can access to the usual ``self.env`` " +"(new API) or ``self.pool`` (old API)." +msgstr "" +"Le framework utilise des objets :py:class:`~connector.session." +"ConnectorSession` pour stocker les ``cr``, ``uid`` et ``context`` dans un :" +"class:`odoo.api.Environment`. Donc depuis une session, nous pouvons " +"accéder aux habituels ``self.env`` (nouvelle API) ou ``self.pool`` (ancienne " +"API)." + +#. module: connector +#: ../../guides/code_overview.rst:64 ../../guides/concepts.rst:20 +msgid "Events" +msgstr "Événements" + +#. module: connector +#: ../../guides/code_overview.rst:66 +msgid "" +"We can create :py:class:`~connector.event.Event` on which we'll be able to " +"subscribe consumers. The connector already integrates the most generic " +"ones: :py:meth:`~connector.event.on_record_create`, :py:meth:`~connector." +"event.on_record_write`, :py:meth:`~connector.event.on_record_unlink`" +msgstr "" +"Nous pouvons créer un :py:class:`~connector.event.Event` sur lequel nous " +"pouvons abonner des consommateurs. Le connecteur fournit d'origine les plus " +"génériques: :py:meth:`~connector.event.on_record_create`, :py:meth:" +"`~connector.event.on_record_write`, :py:meth:`~connector.event." +"on_record_unlink`" + +#. module: connector +#: ../../guides/code_overview.rst:73 +msgid "" +"When we create a ``magento.account.invoice`` record, we want to delay a job " +"to export it to Magento, so we subscribe a new consumer on :py:meth:" +"`~connector.event.on_record_create`::" +msgstr "" +"À la création d'un enregistrement ``magento.account.invoice``, nous voulons " +"lancer un job déporté pour l'exporter vers Magento, donc nous abonnons un " +"nouveau consommateur à l'événement :py:meth:`~connector.event." +"on_record_create`::" + +#. module: connector +#: ../../guides/code_overview.rst:84 +msgid "" +"On the last line, you can notice an ``export_invoice.delay``. We'll discuss " +"about that in Jobs_" +msgstr "" +"Sur la dernière ligne, vous pouvez notez un ``export_invoice.delay``. Nous " +"parlerons de ceci dans Jobs_" + +#. module: connector +#: ../../guides/code_overview.rst:89 +msgid "Jobs" +msgstr "Jobs" + +#. module: connector +#: ../../guides/code_overview.rst:91 +msgid "" +"A :py:class:`~connector.queue.job.Job` is a task to execute later. In that " +"case: create the invoice on Magento." +msgstr "" +"Un :py:class:`~connector.queue.job.Job` est une tâche à exécuter plus tard. " +"Dans le cas présent: créer une facture dans Magento." + +#. module: connector +#: ../../guides/code_overview.rst:94 +msgid "" +"Any function decorated with :py:meth:`~connector.queue.job.job` can be " +"posted in the queue of jobs using a ``delay()`` function and will be run as " +"soon as possible::" +msgstr "" +"N'importe quelle fonction décorée avec :py:meth:`~connector.queue.job.job` " +"peut être envoyée dans la queue de jobs en utilisant la fonction ``delay()`` " +"et sera lancée aussi tôt que possible ::" + +#. module: connector +#: ../../guides/code_overview.rst:107 +msgid "There is a few things happening there:" +msgstr "Voici les choses qui se passent à ce moment :" + +#. module: connector +#: ../../guides/code_overview.rst:109 +msgid "We find the backend on which we'll export the invoice." +msgstr "Nous trouvons le backend vers lequel exporter la facture." + +#. module: connector +#: ../../guides/code_overview.rst:110 +msgid "" +"We build an :py:class:`~connector.connector.Environment` with the current :" +"py:class:`~connector.session.ConnectorSession`, the model we work with and " +"the target backend." +msgstr "" +"Nous construisons un :py:class:`~connector.connector.Environment` avec la :" +"py:class:`~connector.session.ConnectorSession` actuelle, le modèle avec " +"lequel on travaille et le backend cible." + +#. module: connector +#: ../../guides/code_overview.rst:113 +msgid "" +"We get the :py:class:`~connector.connector.ConnectorUnit` responsible for " +"the work using :py:meth:`~connector.connector.Environment." +"get_connector_unit` (according the backend version and the model) and we " +"call ``run()`` on it." +msgstr "" +"Nous récupérons la :py:class:`~connector.connector.ConnectorUnit` " +"responsable du travail grâce à :py:meth:`~connector.connector.Environment." +"get_connector_unit` (en fonction de la version du backend et du modèle) et " +"nous appelons sa méthode ``run()``." + +#. module: connector +#: ../../guides/code_overview.rst:122 ../../guides/concepts.rst:143 +msgid "ConnectorUnit" +msgstr "ConnectorUnit" + +#. module: connector +#: ../../guides/code_overview.rst:124 +msgid "" +"These are all classes which are responsible for a specific work. The main " +"types of :py:class:`~connector.connector.ConnectorUnit` are (the " +"implementation of theses classes belongs to the connectors):" +msgstr "" +"Voici toutes les classes qui sont responsables d'un travail particulier. Les " +"principaux types de :py:class:`~connector.connector.ConnectorUnit` sont " +"(l'implémentation de ces classes fait partie des connecteurs):" + +#. module: connector +#: ../../guides/code_overview.rst:128 +msgid ":py:class:`~connector.connector.Binder`" +msgstr ":py:class:`~connector.connector.Binder`" + +#. module: connector +#: ../../guides/code_overview.rst:133 +msgid ":py:class:`~connector.unit.mapper.Mapper`" +msgstr ":py:class:`~connector.unit.mapper.Mapper`" + +#. module: connector +#: ../../guides/code_overview.rst:138 +msgid ":py:class:`~connector.unit.backend_adapter.BackendAdapter`" +msgstr ":py:class:`~connector.unit.backend_adapter.BackendAdapter`" + +#. module: connector +#: ../../guides/code_overview.rst:140 +msgid "" +"The ``adapters`` implements the discussion with the ``backend's`` APIs. They " +"usually adapt their APIs to a common interface (CRUD)." +msgstr "" +"Les ``adaptateurs`` implémentent le dialogue avec les API du ``backend``. " +"Elles adaptent habituellement leurs APIs à une interface commune (CRUD)." + +#. module: connector +#: ../../guides/code_overview.rst:143 +msgid ":py:class:`~connector.unit.synchronizer.Synchronizer`" +msgstr ":py:class:`~connector.unit.synchronizer.Synchronizer`" + +#. module: connector +#: ../../guides/code_overview.rst:145 +msgid "" +"The ``synchronizers`` are the main piece of a synchronization. They define " +"the flow of a synchronization and use the other :py:class:`~connector." +"connector.ConnectorUnit` (the ones above or specific ones)." +msgstr "" +"Les ``synchroniseurs`` sont la partie principale d'une synchronisation. Ils " +"définissent le flux de synchronisation et utilisent les :py:class:" +"`~connector.connector.ConnectorUnit` (ceux ci-dessus ou des spécifiques)." + +#. module: connector +#: ../../guides/code_overview.rst:150 +msgid "" +"For the export of the invoice, we just need an ``adapter`` and a " +"``synchronizer`` (the real implementation is more complete)::" +msgstr "" +"Pour l'export de la facture, nous avons juste besoin d'un ``adaptateur`` et " +"d'un ``synchroniseur`` (l'implémentation réelle est plus complexe)::" + +#. module: connector +#: ../../guides/concepts.rst:5 +msgid "Connector Concepts" +msgstr "Concepts du connecteur" + +#. module: connector +#: ../../guides/concepts.rst:7 +msgid "" +"The framework to develop connectors is decoupled in small pieces of codes " +"interacting together. Each of them can be used or not in an implementation." +msgstr "" +"Le framework pour développer des connecteur est découplé en composants " +"interagissant ensemble. Chacun d'eux peut être utilisé ou non dans une " +"implémentation." + +#. module: connector +#: ../../guides/concepts.rst:13 +msgid "" +"This document describes them from a high-level point of view and gives " +"pointers to more concrete 'how-to' or small tutorials." +msgstr "" +"Ce document les décrit d'un point de vue haut-niveau et donne des pointeurs " +"vers des « how-to » plus concrets ou de petits tutoriels." + +#. module: connector +#: ../../guides/concepts.rst:25 +msgid "" +"The basic idea is to declare an :py:class:`~connector.event.Event`, for " +"instance :py:class:`~connector.event.on_record_create`. Then each connector " +"has the ability to subscribe one or many function on it. The creation of a " +"record should fire :py:class:`~connector.event.on_record_create`, which will " +"trigger all the subscribed functions." +msgstr "" +"L'idée de base est de déclarer un :py:class:`~connector.event.Event`, par " +"exemple :py:class:`~connector.event.on_record_create`. Grâce à ceci, chaque " +"connecteur a la possibilité d'abonner une ou plusieurs fonctions sur " +"l'événement. La création de l'enregistrement doit alors exécuter :py:class:" +"`~connector.event.on_record_create`, qui va déclencher toutes les fonctions " +"abonnées." + +#. module: connector +#: ../../guides/concepts.rst:32 +msgid "" +"The same event can be shared across several connectors, easing their " +"implementation. For instance, the module connector_ecommerce_ which extends " +"the framework with common e-commerce capabilities, adds its own events " +"common to e-commerce." +msgstr "" +"Le même événement peut être partagé entre plusieurs connecteurs, facilitant " +"ainsi leur implémentation. Par exemple, le module connector_ecommerce_ qui " +"est une extension du framework avec des capacités courantes pour le e-" +"commerce, ajoute ses propres événements dédiés au e-commerce." + +#. module: connector +#: ../../guides/concepts.rst:38 ../../guides/concepts.rst:81 +#: ../../guides/concepts.rst:115 ../../guides/concepts.rst:136 +msgid "A connectors developer is mostly interested by:" +msgstr "Un développeur de connecteur est principalement intéressé par :" + +#. module: connector +#: ../../guides/concepts.rst:40 +msgid "" +"register a new function on an event (see :py:class:`connector.event.Event`)" +msgstr "" +"abonner une nouvelle fonction à un événement (voir :py:class:`connector." +"event.Event`)" + +#. module: connector +#: ../../guides/concepts.rst:41 +msgid "" +"unregister a function from an event (see :py:meth:`connector.event.Event." +"unsubscribe`)" +msgstr "" +"désabonner une fonction d'un événement (voir :py:meth:`connector.event.Event." +"unsubscribe`)" + +#. module: connector +#: ../../guides/concepts.rst:42 +msgid "" +"replace a consumer function by another one (see :py:class:`connector.event." +"Event`)" +msgstr "" +"remplacer une fonction consommatrice par une autre (voir :py:class:" +"`connector.event.Event`)" + +#. module: connector +#: ../../guides/concepts.rst:43 +msgid "" +"filter the events by model, so a subscribed function will be triggered only " +"if the event happens on a registered model" +msgstr "" +"filtrer les événements par modèle, de sorte qu'une fonction abonnée ne soit " +"déclenchée que pour l'événement d'un modèle particulier" + +#. module: connector +#: ../../guides/concepts.rst:50 +msgid "Jobs Queue" +msgstr "Queue de jobs" + +#. module: connector +#: ../../guides/concepts.rst:52 +msgid "" +"This section summarises the Job's Queue, which articulates around several " +"classes, in broad terms, :py:class:`~connector.queue.job.Job` are executed " +"by a :py:class:`~connector.queue.worker.Worker` which stores them in a :py:" +"class:`~connector.queue.queue.JobsQueue`." +msgstr "" +"Cette section résume le principe des queues de jobs, qui s'articule autour " +"de quelques classes, dans les grandes lignes, les :py:class:`~connector." +"queue.job.Job` sont exécutés par un :py:class:`~connector.queue.worker." +"Worker` qui les stocke dans une :py:class:`~connector.queue.queue.JobsQueue`." + +#. module: connector +#: ../../guides/concepts.rst:61 +msgid "" +"Jobs are stored in the :py:class:`~connector.queue.model.QueueJob` model." +msgstr "" +"Les jobs son stockés dans le modèle :py:class:`~connector.queue.model." +"QueueJob`." + +#. module: connector +#: ../../guides/concepts.rst:64 +msgid "" +"Workers are stored in the :py:class:`~connector.queue.model.QueueWorker` " +"model. A :py:class:`~connector.queue.worker.WorkerWatcher` create or destroy " +"new workers when new :py:class:`~odoo.modules.registry.Registry` are " +"created or destroyed, and signal the aliveness of the workers." +msgstr "" +"Les workers sont stockés dans le modèle :py:class:`~connector.queue.model." +"QueueWorker`. Un :py:class:`~connector.queue.worker.WorkerWatcher` crée ou " +"détruit de nouveaux workers quand de nouveaux :py:class:`~odoo.modules." +"registry.Registry` sont créés ou détruits, et signale si les workers sont en " +"vie ou non." + +#. module: connector +#: ../../guides/concepts.rst:70 +msgid "" +"Jobs are assigned to a worker in the database by a cron. The worker loads " +"all the jobs assigned to itself in memory in the :py:class:`~connector.queue." +"queue.JobsQueue`. When a worker is dead, it is removed from the database, so " +"the jobs are freeed from the worker and can be assigned to another one." +msgstr "" +"Les jobs sont affectés à un worker dans la base de données par une tâche " +"récurrente (cron). Le worker charge en mémoire tous les jobs qui lui sont " +"affectés, dans la :py:class:`~connector.queue.queue.JobsQueue`. Quand un " +"worker s'arrête, il est supprimé de la base de données, de façon que les " +"jobs soient libérés et affectés à un autre worker." + +#. module: connector +#: ../../guides/concepts.rst:83 +msgid "Delay a job (see the decorator :py:func:`~connector.queue.job.job`)" +msgstr "" +"Déporter un job (voir le décorateur :py:func:`~connector.queue.job.job`)" + +#. module: connector +#: ../../guides/concepts.rst:97 +msgid "Backend" +msgstr "Backend" + +#. module: connector +#: ../../guides/concepts.rst:99 +msgid "" +"A :py:class:`~connector.backend.Backend` is a reference to an external " +"system or service." +msgstr "" +"Un :py:class:`~connector.backend.Backend` est une référence à un système ou " +"service externe à Odoo." + +#. module: connector +#: ../../guides/concepts.rst:102 +msgid "" +"A backend is defined by a name and a version. For instance ``Magento 1.7``." +msgstr "" +"Un backend est défini par un nom et une version. Par exemple ``Magento 1.7``." + +#. module: connector +#: ../../guides/concepts.rst:105 +msgid "" +"A reference can have a parent. The instance ``Magento 1.7`` is the child of " +"``Magento``." +msgstr "" +"Une référence peut avoir un parent. L'instance ``Magento 1.7`` est fille de " +"``Magento``." + +#. module: connector +#: ../../guides/concepts.rst:108 +msgid "" +":py:class:`~connector.connector.ConnectorUnit` classes are registered on the " +"backends. Then, we are able to ask a registered class to a backend. If no " +"class is found, it will search in its parent backend." +msgstr "" +"Les classes :py:class:`~connector.connector.ConnectorUnit` sont inscrites " +"dans les backends. Ceci permet de récupérer une classe inscrite dans le " +"backend. Si aucune classe n'est trouvée, elle est cherchée dans le backend " +"parent." + +#. module: connector +#: ../../guides/concepts.rst:112 +msgid "" +"It is always accompanied by a concrete subclass of the model :py:class:" +"`~connector.models.backend_model.connector_backend`." +msgstr "" +"Il est toujours accompagné d'une sous-classe concrète du modèle :py:class:" +"`~connector.models.backend_model.connector_backend`." + +#. module: connector +#: ../../guides/concepts.rst:117 +msgid "Declare the backends (see :py:class:`connector.backend.Backend`)" +msgstr "Déclarer les backends (voir :py:class:`connector.backend.Backend`)" + +#. module: connector +#: ../../guides/concepts.rst:118 +msgid "" +"Register a ConnectorUnit on a backend (see :py:class:`connector.backend." +"Backend`)" +msgstr "" +"Inscrire un ConnectorUnit dans un backend (voir :py:class:`connector.backend." +"Backend`)" + +#. module: connector +#: ../../guides/concepts.rst:119 +msgid "" +"Replace a ConnectorUnit on a backend (see :py:class:`connector.backend." +"Backend`)" +msgstr "" +"Remplacer un ConnectorUnit dans un backend (voir :py:class:`connector." +"backend.Backend`)" + +#. module: connector +#: ../../guides/concepts.rst:120 +msgid "" +"Use a different ConnectorUnit for a different version of a backend (see :py:" +"class:`connector.backend.Backend`)" +msgstr "" +"Utiliser un ConnectorUnit différent pour une version différente d'un backend " +"(voir :py:class:`connector.backend.Backend`)" + +#. module: connector +#: ../../guides/concepts.rst:127 +msgid "" +"An :py:class:`~connector.connector.Environment` is the scope from which we " +"will do synchronizations." +msgstr "" +"Un :py:class:`~connector.connector.Environment` est le périmètre à partir " +"duquel nous allons faire des synchronisations." + +#. module: connector +#: ../../guides/concepts.rst:130 +msgid "" +"It contains a :py:class:`~connector.backend.Backend`, a record of a concrete " +"subclass of the model :py:class:`~connector.models.backend_model." +"connector_backend`, a :py:class:`~connector.session.Session` and the name of " +"the model to work with." +msgstr "" +"Il contient un :py:class:`~connector.backend.Backend`, un enregistrement " +"d'une sous-classe concrète du modèle :py:class:`~connector.models.backend_model." +"connector_backend`, une :py:class:`~connector.session.Session` et le nom du " +"modèle avec lequel travailler." + +#. module: connector +#: ../../guides/concepts.rst:138 +msgid "" +"Get a connectorUnit from an environment (:py:meth:`connector.connector." +"ConnectorUnit.unit_for`, :py:meth:`connector.connector.ConnectorUnit." +"binder_for`)" +msgstr "" +"Récupère un ConnectorUnit depuis un environnement (:py:meth:`connector." +"connector.ConnectorUnit.unit_for`, :py:meth:`connector.connector." +"ConnectorUnit.binder_for`)" + +#. module: connector +#: ../../guides/concepts.rst:145 +msgid "" +":py:class:`~connector.connector.ConnectorUnit` are pluggable classes used " +"for the synchronizations with the external systems." +msgstr "" +"Les :py:class:`~connector.connector.ConnectorUnit` sont des classes " +"modulables utilisées pour la synchronisation avec des systèmes externes." + +#. module: connector +#: ../../guides/concepts.rst:149 +msgid "" +"The connector defines some base classes, which you can find below. Note that " +"you can define your own ConnectorUnits as well." +msgstr "" +"Le connecteur définit des classes de bases que vous pouvez trouver ci-" +"dessous. Notez que vous pouvez aussi définir vos propres ConnectorUnits." + +#. module: connector +#: ../../guides/concepts.rst:153 +msgid "Mappings" +msgstr "Mappings" + +#. module: connector +#: ../../guides/concepts.rst:155 +msgid "The base class is :py:class:`connector.unit.mapper.Mapper`." +msgstr "La classe de base est :py:class:`connector.unit.mapper.Mapper`." + +#. module: connector +#: ../../guides/concepts.rst:160 +msgid "It supports:" +msgstr "Il prend en charge :" + +#. module: connector +#: ../../guides/concepts.rst:163 +msgid "direct mappings" +msgstr "les mapping directs" + +#. module: connector +#: ../../guides/concepts.rst:163 +msgid "Fields *a* is written in field *b*." +msgstr "Le champ *a* est écrit dans le champ *b*." + +#. module: connector +#: ../../guides/concepts.rst:169 +msgid "method mappings" +msgstr "Les mapping par méthode" + +#. module: connector +#: ../../guides/concepts.rst:166 +msgid "" +"A method is used to convert one or many fields to one or many fields, with " +"transformation. It can be filtered, for example only applied when the record " +"is created or when the source fields are modified." +msgstr "" +"Une méthode est utilisée pour convertir un ou plusieurs champs en un ou " +"plusieurs autres champs, avec transformation éventuelle. Il peut être " +"filtré, par exemple appliqué uniquement lorsque l'enregistrement est créé ou " +"quand les champs source sont modifiés." + +#. module: connector +#: ../../guides/concepts.rst:173 +msgid "submapping" +msgstr "Sous-mapping" + +#. module: connector +#: ../../guides/concepts.rst:172 +msgid "a sub-record (lines of a sale order) is converted using another Mapper" +msgstr "" +"Un sous-enregistrement (ligne d'un bon de commande) est converti grâce à un " +"autre Mapper" + +#. module: connector +#: ../../guides/concepts.rst:176 +msgid "Synchronizers" +msgstr "Synchroniseurs" + +#. module: connector +#: ../../guides/concepts.rst:178 +msgid "The base class is :py:class:`connector.unit.synchronizer.Synchronizer`." +msgstr "" +"La classe de base est :py:class:`connector.unit.synchronizer.Synchronizer`." + +#. module: connector +#: ../../guides/concepts.rst:180 +msgid "" +"A synchronizer defines the flow of a synchronization with a backend. It can " +"be a record's import or export, a deletion of something, or anything else. " +"For instance, it will use the mappings to convert the data between both " +"systems, the backend adapters to read or write data on the backend and the " +"binders to create the link between them." +msgstr "" +"Un synchroniseur définit le flux de la synchronisation avec un backend. Il " +"peut correspondre à un import ou un export, une suppression de quelque " +"chose, ou n'importe quoi d'autre. Par exemple, il peut utiliser les mappeurs " +"pour convertir des données entre les deux systèmes, les adaptateurs de " +"backend pour lire ou écrire les données sur le backend et les binders pour " +"créer le lien entre eux." + +#. module: connector +#: ../../guides/concepts.rst:189 +msgid "Backend Adapters" +msgstr "Adaptateurs de backend" + +#. module: connector +#: ../../guides/concepts.rst:191 +msgid "" +"The base class is :py:class:`connector.unit.backend_adapter.BackendAdapter`." +msgstr "" +"La classe de base est :py:class:`connector.unit.backend_adapter." +"BackendAdapter`." + +#. module: connector +#: ../../guides/concepts.rst:194 +msgid "" +"An external adapter has a common interface to speak with the backend. It " +"translates the basic orders (search, read, write) to the protocol used by " +"the backend." +msgstr "" +"Un adaptateur externe possède une interface commune pour parler avec le " +"backend. Il traduit les commandes basiques (recherche, lecture, écriture) " +"vers le protocole utilisé par le backend." + +#. module: connector +#: ../../guides/concepts.rst:199 +msgid "Binders" +msgstr "Binders (Liants)" + +#. module: connector +#: ../../guides/concepts.rst:201 +msgid "The base class is :py:class:`connector.connector.Binder`." +msgstr "La classe de base est :py:class:`connector.connector.Binder`." + +#. module: connector +#: ../../guides/concepts.rst:217 +msgid "" +"The proposed implementation for the connectors widely use the `_inherits` " +"capabilities." +msgstr "" +"L'implémentation proposée pour les connecteurs utilise largement les " +"capacités de l'`_inherits`." + +#. module: connector +#: ../../guides/concepts.rst:220 +msgid "Say we import a customer from *Magento*." +msgstr "Disons que nous importons un client depuis *Magento*." + +#. module: connector +#: ../../guides/concepts.rst:222 +msgid "" +"We create a `magento.res.partner` model, which `_inherits` `res.partner`." +msgstr "" +"Nous créons un modèle `magento.res.partner`, qui `_inherits` `res.partner`." + +#. module: connector +#: ../../guides/concepts.rst:228 +msgid "" +"It also stores all the necessary metadata related to this customer coming " +"from Magento." +msgstr "" +"Il stocke également toutes les métadonnées nécessaires à ce client venant de " +"Magento" + +#. module: connector +#: ../../guides/multiprocessing.rst:6 +msgid "Use the connector with multiprocessing" +msgstr "Connecteur et multiprocessing" + +#. module: connector +#: ../../guides/multiprocessing.rst:22 +msgid "Example::" +msgstr "Exemple ::" + +#. module: connector +#: ../../guides/multiprocessing.rst:27 +msgid "" +"The 'Enqueue Jobs' scheduled action is useless when multiprocessing is used." +msgstr "L'action planifiée 'Enqueue Jobs' est inutile en mode multi-processus." + +#. module: connector +#: ../../guides/multiprocessing.rst:34 +msgid "" +"The Magento Connector's buildout contains builtin commands to launch the " +"workers: :ref:`connectormagento:installation-with-buildout`" +msgstr "" +"Le `buildout` du connecteur Magento contient des commandes intégrées pour " +"lancer les workers : :ref:`connectormagento:installation-with-buildout`" + +#. module: connector +#: ../../guides/bootstrap_connector.rst:13 +msgid "`Odoo Magento Connector`_" +msgstr "`Connecteur Odoo Magento`_" + +#. module: connector +#: ../../guides/bootstrap_connector.rst:14 +msgid "`Odoo Prestashop Connector`_" +msgstr "`Connecteur Odoo Prestashop`_" + +#. module: connector +#: ../../guides/bootstrap_connector.rst:19 +msgid "" +"For the sake of the example, we'll imagine we have to synchronize Odoo with " +"a coffee machine." +msgstr "" +"Pour cet exemple nous allons imaginer que nous devons synchroniser Odoo avec " +"une machine à café." + +#. module: connector +#: ../../guides/bootstrap_connector.rst:24 +msgid "Odoo Manifest" +msgstr "" + +#. module: connector +#: ../../guides/bootstrap_connector.rst:26 +msgid "" +"As we want to synchronize Odoo with a coffee machine, we'll name our " +"connector connector_coffee." +msgstr "" +"Comme nous voulons synchroniser Odoo avec une machine à café, nous allons " +"nommer notre connecteur connector_coffee" + +#. module: connector +#: ../../guides/bootstrap_connector.rst:29 +msgid "" +"First, we need to create the Odoo addons itself, editing the " +"``connector_coffee/__odoo__.py`` manifest." +msgstr "" +"Tout d'abord, nous devons créer le module Odoo lui-même, en modifiant le " +"fichier ``connector_coffee/__odoo__.py``." + +#. module: connector +#: ../../guides/bootstrap_connector.rst:85 +msgid "" +"The reason for this is that Odoo may import the Python modules of " +"uninstalled modules, so it automatically registers the events and " +"ConnectorUnit classes, even for uninstalled modules." +msgstr "" +"La raison de ce fonctionnement est qu'Odoo importe les modules Python des " +"addons non installés, donc il inscrit automatiquement les événements et les " +"classes ConnectorUnit, même pour les modules non installés." + +#. module: connector +#: ../../guides/bootstrap_connector.rst:244 +msgid "" +"Their implementation can vary a lot. Have a look on the `Odoo Magento " +"Connector`_ and `Odoo Prestashop Connector`_ projects." +msgstr "" +"Leur implémentation peut varier énormément. Jetez un œil aux projets " +"`Connecteur Odoo Magento`_ et `Connecteur Odoo Prestashop`_." + +#. module: connector +#: ../../guides/code_overview.rst:34 +msgid "" +"The ``binding`` is the link between an Odoo record and an external record. " +"There is no forced implementation for the ``bindings``. The most " +"straightforward techniques are: storing the external ID in the same model " +"(``account.invoice``), in a new link model or in a new link model which " +"``_inherits`` ``account.invoice``. Here we choose the latter solution::" +msgstr "" +"Un ``binding`` est ce qui permet de lier un enregistrement Odoo et un " +"enregistrement externe. Il n'y a pas d'obligation pour l'implémentation des " +"``liaisons``. Les techniques les plus évidentes sont: stocker les ID " +"externes dans le même modèle (``account.invoice``), dans un modèle de " +"liaison ou dans un modèle de laison qui ``_inherits`` ``account.invoice``. " +"Ici nous choisissons la dernière solution ::" + +#. module: connector +#: ../../guides/code_overview.rst:130 +msgid "" +"The ``binders`` give the external ID or Odoo ID from respectively an Odoo ID " +"or an external ID." +msgstr "" +"Les ``binders`` (liants) donnent l'ID externe ou l'ID Odoo en fonction, " +"respectivement, d'un ID Odoo ou d'un ID externe." + +#. module: connector +#: ../../guides/code_overview.rst:135 +msgid "" +"The ``mappers`` transform a external record into an Odoo record or " +"conversely." +msgstr "" +"Les ``mappeurs`` transforment un enregistrement externe en enregistrement " +"Odoo ou l'inverse." + +#. module: connector +#: ../../guides/concepts.rst:11 +msgid "An example of implementation is the `Odoo Magento Connector`_." +msgstr "Un exemple d'implémentation est le `Connecteur Odoo Magento`_." + +#. module: connector +#: ../../guides/concepts.rst:22 +msgid "" +"Events are hooks in Odoo on which we can plug some actions. They are based " +"on an Observer pattern." +msgstr "" +"Les événements sont des points d'accroche dans Odoo sur lesquels on peut " +"brancher des actions. Ils sont basés sur le motif de conception « " +"Observateur »." + +#. module: connector +#: ../../guides/concepts.rst:77 +msgid "" +"When multiple Odoo processes are running, a worker per process is running, " +"but only those which are *CronWorkers* enqueue and execute jobs, to avoid to " +"clutter the HTTP processes." +msgstr "" +"Si plusieurs processus Odoo sont en marche, il y a un worker par processus, " +"mais seuls ceux qui sont des *CronWorkers* traitent les jobs dans la queue, " +"pour éviter d'encombrer les processus HTTP." + +#. module: connector +#: ../../guides/concepts.rst:90 +msgid "" +"A :py:class:`~connector.session.ConnectorSession` is a container for the " +"usual ``cr``, ``uid``, ``context`` used in Odoo. Now, it contains the Odoo " +"``Environment`` as ``self.env``. We use them accross the connectors." +msgstr "" +"Une :py:class:`~connector.session.ConnectorSession` est un conteneur pour " +"les classiques ``cr``, ``uid``, ``context`` utilisés dans Odoo. Maintenant " +"il contient l'``Environment`` Odoo dans ``self.env``. Nous les utilisons au " +"sein des connecteurs." + +#. module: connector +#: ../../guides/concepts.rst:157 +msgid "" +"A mapping translates an external record to an Odoo record and conversely." +msgstr "" +"Un mapping convertit un enregistrement externe en un enregistrement Odoo et " +"inversement." + +#. module: connector +#: ../../guides/concepts.rst:204 +msgid "" +"Binders are classes which know how to find the external ID for an Odoo ID, " +"how to find the Odoo ID for an external ID and how to create the binding " +"between them." +msgstr "" +"Les Binders sont des classes qui savent comment trouver l'ID externe depuis " +"un ID Odoo, comment trouver l'ID Odoo depuis un ID externe et comment créer " +"le lien entre elles." + +#. module: connector +#: ../../guides/concepts.rst:215 +msgid "Here a binding means the link of a record between Odoo and a backend." +msgstr "" +"Ici, un « binding » signifie le lien d'un enregistrement entre Odoo et un " +"backend." + +#. module: connector +#: ../../guides/concepts.rst:225 +msgid "" +"This model, called a *binding* model, knows the ID of the partner in Odoo, " +"the ID in Magento and the relation to the backend model." +msgstr "" +"Ce modèle, appelé modèle de *binding* (liaison), connaît les ID du `partner` " +"dans Odoo, l'ID dans Magento et la relation avec le modèle backend." + +#. module: connector +#: ../../guides/multiprocessing.rst:8 +msgid "" +"When Odoo is launched with 1 process, the jobs worker will run threaded in " +"the same process." +msgstr "" +"Quand Odoo est lancé avec un seul processus, le worker de jobs fonctionne " +"dans un thread." + +#. module: connector +#: ../../guides/multiprocessing.rst:11 +msgid "" +"When Odoo is launched with multiple processes using the option ``--" +"workers``, the jobs workers are not independant processes, however, you have " +"to launch them separately with the script ``odoo-connector-worker`` " +"located in the connector module." +msgstr "" +"Quand Odoo est lancé en multi-processus grâce à l'option ``--workers``, les " +"workers de jobs ne sont pas des processus indépendants, mais vous devez les " +"lancer séparément avec le script ``odoo-connector-worker`` situé dans le " +"module `connector`." + +#. module: connector +#: ../../guides/multiprocessing.rst:16 +msgid "" +"It takes the same arguments and configuration file than the Odoo server." +msgstr "" +"Il prend les mêmes arguments et fichier de configuration que le serveur Odoo." + +#. module: connector +#: ../../guides/multiprocessing.rst:19 +msgid "" +"The Python path must contain the path to the Odoo server when ``odoo-" +"connector-worker`` is launched." +msgstr "" +"Le `path` de Python doit contenir le chemin vers le serveur Odoo quand " +"``odoo-connector-worker`` est lancé." + +#. module: connector +#: ../../guides/multiprocessing.rst:30 +msgid "" +"The ``odoo-connector-worker`` should not be launched alongside Odoo when " +"the latter does not run in multiprocess mode, because the interprocess " +"signaling would not be done." +msgstr "" +"Le script ``odoo-connector-worker`` ne doit pas être lancé avec Odoo " +"quand ce dernier ne fonctionne pas en multi-processus, parce que les signaux " +"inter-processus ne seraient pas transmis." + +#~ msgid "`Odoo Magento Connector`_" +#~ msgstr "`Connecteur Odoo Magento`_" + +#~ msgid "`Odoo Prestashop Connector`_" +#~ msgstr "`Connecteur Odoo Prestashop`_" + +#~ msgid "" +#~ "For the sake of the example, we'll imagine we have to synchronize Odoo " +#~ "with a coffee machine." +#~ msgstr "" +#~ "Pour cet exemple nous allons imaginer que nous devons synchroniser " +#~ "Odoo avec une machine à café." + +#~ msgid "Odoo Manifest" +#~ msgstr "Manifest Odoo" + +#~ msgid "" +#~ "As we want to synchronize Odoo with a coffee machine, we'll name our " +#~ "connector connector_coffee." +#~ msgstr "" +#~ "Comme nous voulons synchroniser Odoo avec une machine à café, nous " +#~ "allons nommer notre connecteur connector_coffee" + +#~ msgid "" +#~ "First, we need to create the Odoo addons itself, editing the " +#~ "``connector_coffee/__odoo__.py`` manifest." +#~ msgstr "" +#~ "Tout d'abord, nous devons créer le module Odoo lui-même, en modifiant " +#~ "le fichier ``connector_coffee/__odoo__.py``." + +#~ msgid "" +#~ "The reason for this is that Odoo may import the Python modules of " +#~ "uninstalled modules, so it automatically registers the events and " +#~ "ConnectorUnit classes, even for uninstalled modules." +#~ msgstr "" +#~ "La raison de ce fonctionnement est qu'Odoo importe les modules Python " +#~ "des addons non installés, donc il inscrit automatiquement les événements " +#~ "et les classes ConnectorUnit, même pour les modules non installés." + +#~ msgid "" +#~ "Their implementation can vary a lot. Have a look on the `Odoo Magento " +#~ "Connector`_ and `Odoo Prestashop Connector`_ projects." +#~ msgstr "" +#~ "Leur implémentation peut varier énormément. Jetez un œil aux projets " +#~ "`Connecteur Odoo Magento`_ et `Connecteur Odoo Prestashop`_." + +#~ msgid "" +#~ "The ``binding`` is the link between an Odoo record and an external " +#~ "record. There is no forced implementation for the ``bindings``. The most " +#~ "straightforward techniques are: storing the external ID in the same model " +#~ "(``account.invoice``), in a new link model or in a new link model which " +#~ "``_inherits`` ``account.invoice``. Here we choose the latter solution::" +#~ msgstr "" +#~ "Un ``binding`` est ce qui permet de lier un enregistrement Odoo et un " +#~ "enregistrement externe. Il n'y a pas d'obligation pour l'implémentation " +#~ "des ``liaisons``. Les techniques les plus évidentes sont: stocker les ID " +#~ "externes dans le même modèle (``account.invoice``), dans un modèle de " +#~ "liaison ou dans un modèle de laison qui ``_inherits`` ``account." +#~ "invoice``. Ici nous choisissons la dernière solution ::" + +#~ msgid "" +#~ "The ``binders`` give the external ID or Odoo ID from respectively an " +#~ "Odoo ID or an external ID." +#~ msgstr "" +#~ "Les ``binders`` (liants) donnent l'ID externe ou l'ID Odoo en " +#~ "fonction, respectivement, d'un ID Odoo ou d'un ID externe." + +#~ msgid "" +#~ "The ``mappers`` transform a external record into an Odoo record or " +#~ "conversely." +#~ msgstr "" +#~ "Les ``mappeurs`` transforment un enregistrement externe en enregistrement " +#~ "Odoo ou l'inverse." + +#~ msgid "An example of implementation is the `Odoo Magento Connector`_." +#~ msgstr "Un exemple d'implémentation est le `Connecteur Odoo Magento`_." + +#~ msgid "" +#~ "When multiple Odoo processes are running, a worker per process is " +#~ "running, but only those which are *CronWorkers* enqueue and execute jobs, " +#~ "to avoid to clutter the HTTP processes." +#~ msgstr "" +#~ "Si plusieurs processus Odoo sont en marche, il y a un worker par " +#~ "processus, mais seuls ceux qui sont des *CronWorkers* traitent les jobs " +#~ "dans la queue, pour éviter d'encombrer les processus HTTP." + +#~ msgid "" +#~ "A :py:class:`~connector.session.ConnectorSession` is a container for the " +#~ "usual ``cr``, ``uid``, ``context`` used in Odoo. Now, it contains the " +#~ "Odoo ``Environment`` as ``self.env``. We use them accross the connectors." +#~ msgstr "" +#~ "Une :py:class:`~connector.session.ConnectorSession` est un conteneur pour " +#~ "les classiques ``cr``, ``uid``, ``context`` utilisés dans Odoo. " +#~ "Maintenant il contient l'``Environment`` Odoo dans ``self.env``. Nous les " +#~ "utilisons au sein des connecteurs." + +#~ msgid "" +#~ "A mapping translates an external record to an Odoo record and " +#~ "conversely." +#~ msgstr "" +#~ "Un mapping convertit un enregistrement externe en un enregistrement " +#~ "Odoo et inversement." + +#~ msgid "" +#~ "Binders are classes which know how to find the external ID for an Odoo " +#~ "ID, how to find the Odoo ID for an external ID and how to create the " +#~ "binding between them." +#~ msgstr "" +#~ "Les Binders sont des classes qui savent comment trouver l'ID externe " +#~ "depuis un ID Odoo, comment trouver l'ID Odoo depuis un ID externe " +#~ "et comment créer le lien entre elles." + +#~ msgid "" +#~ "Here a binding means the link of a record between Odoo and a backend." +#~ msgstr "" +#~ "Ici, un « binding » signifie le lien d'un enregistrement entre Odoo et " +#~ "un backend." + +#~ msgid "" +#~ "This model, called a *binding* model, knows the ID of the partner in " +#~ "Odoo, the ID in Magento and the relation to the backend model." +#~ msgstr "" +#~ "Ce modèle, appelé modèle de *binding* (liaison), connaît les ID du " +#~ "`partner` dans Odoo, l'ID dans Magento et la relation avec le modèle " +#~ "backend." + +#~ msgid "" +#~ "When Odoo is launched with 1 process, the jobs worker will run " +#~ "threaded in the same process." +#~ msgstr "" +#~ "Quand Odoo est lancé avec un seul processus, le worker de jobs " +#~ "fonctionne dans un thread." + +#~ msgid "" +#~ "When Odoo is launched with multiple processes using the option ``--" +#~ "workers``, the jobs workers are not independant processes, however, you " +#~ "have to launch them separately with the script ``odoo-connector-" +#~ "worker`` located in the connector module." +#~ msgstr "" +#~ "Quand Odoo est lancé en multi-processus grâce à l'option ``--" +#~ "workers``, les workers de jobs ne sont pas des processus indépendants, " +#~ "mais vous devez les lancer séparément avec le script ``odoo-connector-" +#~ "worker`` situé dans le module `connector`." + +#~ msgid "" +#~ "It takes the same arguments and configuration file than the Odoo " +#~ "server." +#~ msgstr "" +#~ "Il prend les mêmes arguments et fichier de configuration que le serveur " +#~ "Odoo." + +#~ msgid "" +#~ "The Python path must contain the path to the Odoo server when " +#~ "``odoo-connector-worker`` is launched." +#~ msgstr "" +#~ "Le `path` de Python doit contenir le chemin vers le serveur Odoo quand " +#~ "``odoo-connector-worker`` est lancé." + +#~ msgid "" +#~ "The ``odoo-connector-worker`` should not be launched alongside Odoo " +#~ "when the latter does not run in multiprocess mode, because the " +#~ "interprocess signaling would not be done." +#~ msgstr "" +#~ "Le script ``odoo-connector-worker`` ne doit pas être lancé avec " +#~ "Odoo quand ce dernier ne fonctionne pas en multi-processus, parce que " +#~ "les signaux inter-processus ne seraient pas transmis." + +#~ msgid "" +#~ "Events are hooks in Odoo on which we can plug some actions. They are " +#~ "based on an Observer pattern." +#~ msgstr "" +#~ "Les événements sont des points d'accroche dans Odoo sur lesquels on " +#~ "peut brancher des actions. Ils sont basés sur le motif de conception « " +#~ "Observateur »." diff --git a/connector/doc/locale/fr/LC_MESSAGES/index.po b/connector/doc/locale/fr/LC_MESSAGES/index.po new file mode 100644 index 000000000..0527a0e4a --- /dev/null +++ b/connector/doc/locale/fr/LC_MESSAGES/index.po @@ -0,0 +1,318 @@ +# +msgid "" +msgstr "" +"Project-Id-Version: Connector\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-04-15 22:28+0300\n" +"PO-Revision-Date: 2015-05-05 11:52+0100\n" +"Last-Translator: Guewen Baconnier \n" +"Language-Team: fr \n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 1.5.4\n" + +#. module: connector +#: ../../index.rst:21 +msgid "*Subscribe to the* `project's mailing list`_" +msgstr "*Inscrivez-vous à la* `project's mailing list`_ *(en anglais)*" + +#. module: connector +#: ../../index.rst:23 +msgid "*Learn how to* :ref:`contribute`" +msgstr "*Découvrez comment* :ref:`contribute`" + +#. module: connector +#: ../../index.rst:27 +msgid "Core Features" +msgstr "Fonctionnalités de base" + +#. module: connector +#: ../../index.rst:29 +msgid "" +"**100% Open Source** (`LGPL version 3`_): the full `source code is available " +"on GitHub`_" +msgstr "" +"**100% Open Source** (`LGPL version 3`_): la totalité du `code source est " +"disponible sur GitHub`_" + +#. module: connector +#: ../../index.rst:33 +msgid "" +"**Robust for high volumetries** and **easy to monitor** thanks to a :ref:" +"`jobs-queue`." +msgstr "" +"**Robuste pour des volumétries importantes** et **faciler à surveiller** " +"grâce à la :ref:`jobs-queue`." + +#. module: connector +#: ../../index.rst:34 +msgid "" +"A flexible set of building blocks, it does not force to a certain " +"implementation but leaves the final choice to the developer on how to use " +"the proposed pieces." +msgstr "" +"Un ensemble flexible de blocs de construction : il n'oblige pas à respecter " +"une implémentation particulière mais laisse le choix final au développeur " +"sur la manière d'utiliser les composants." + +#. module: connector +#: ../../index.rst:37 +msgid "See a :ref:`code-overview` with examples of code" +msgstr "Voir le :ref:`code-overview` et les exemples de code" + +#. module: connector +#: ../../index.rst:48 +msgid "Connectors based on the framework" +msgstr "Connecteurs basés sur le framework" + +#. module: connector +#: ../../index.rst:50 +msgid "`Magento Connector `_" +msgstr "`Connecteur Magento `_" + +#. module: connector +#: ../../index.rst:51 +msgid "`Prestashop Connector `_" +msgstr "`Connecteur Prestashop `_" + +#. module: connector +#: ../../index.rst:52 +msgid "`solerp (Solr Connector) `_" +msgstr "`solerp (Connecteur Solr) `_" + +#. module: connector +#: ../../index.rst:54 +msgid "`CMIS `_" +msgstr "`Connecteur CMIS `_" + +#. module: connector +#: ../../index.rst:58 +msgid "" +"Develop easily and rapidly your own connector based on this powerful " +"framework and list your project on this page! Examples:" +msgstr "" +"Développez facilement et rapidement votre propre connecteur basé sur ce " +"puissant framework et ajoutez votre projet sur cette page ! Exemples :" + +#. module: connector +#: ../../index.rst:69 +msgid "Overview" +msgstr "Présentation" + +#. module: connector +#: ../../index.rst:79 +msgid "Top financial contributors" +msgstr "Principaux contributeurs financiers" + +#. module: connector +#: ../../index.rst:90 +msgid "*See all the project's* :ref:`financial-contributors`." +msgstr "*Voir tous les* :ref:`financial-contributors` *du projet*." + +#. module: connector +#: ../../index.rst:94 +msgid "Project" +msgstr "Projet" + +#. module: connector +#: ../../index.rst:107 +msgid "Developer's guide" +msgstr "Guide du développeur" + +#. module: connector +#: ../../index.rst:118 +msgid "API Reference" +msgstr "Référence de l'API" + +#. module: connector +#: ../../index.rst:136 +msgid "Indices and tables" +msgstr "Index et tables" + +#. module: connector +#: ../../index.rst:138 +msgid ":ref:`genindex`" +msgstr ":ref:`genindex`" + +#. module: connector +#: ../../index.rst:139 +msgid ":ref:`modindex`" +msgstr ":ref:`modindex`" + +#. module: connector +#: ../../index.rst:140 +msgid ":ref:`search`" +msgstr ":ref:`search`" + +#. module: connector +#: ../../index.rst:8 +msgid "Odoo Connector" +msgstr "Odoo Connector" + +#. module: connector +#: ../../index.rst:10 +msgid "" +"Odoo Connector is a powerful framework to develop any kind of bi-directional " +"connector between `Odoo`_ (Open Source ERP) and any other software or " +"service." +msgstr "" +"`Odoo Connector` est un puissant framework de développement de connecteur bi-" +"directionnel entre `Odoo`_ (ERP Open Source) et tout autre logiciel ou " +"service." + +#. module: connector +#: ../../index.rst:14 +msgid "" +"This Odoo add-on has a modular and generic core, with the ability to be " +"extended with additional modules for new features or customizations." +msgstr "" +"Ce module Odoo a un cœur modulaire et générique, capable d'être lui-même " +"étendu grâce à des modules additionnels, pour ajouter des nouvelles " +"fonctions ou des personnalisations." + +#. module: connector +#: ../../index.rst:18 +msgid "" +"The development of Odoo Connector has been started by `Camptocamp`_ and is " +"now maintained by `Camptocamp`_, `Akretion`_ and several :ref:`contributors`." +msgstr "" +"Le développement du Connecteur Odoo a été démarré par `Camptocamp`_ et est " +"maintenu par `Camptocamp`_, `Akretion`_ et d'autres :ref:`contributors`." + +#. module: connector +#: ../../index.rst:31 +msgid "" +"Not only designed to connect Odoo with e-commerce backends, rather it is " +"**adaptable** to connect Odoo with any type of service." +msgstr "" +"Pas uniquement conçu pour connecter Odoo à des backend e-commerce, mais " +"**adaptable** pour connecter Odoo à tout type de service." + +#. module: connector +#: ../../index.rst:53 +msgid "" +"`Odoo Multi Company `_" +msgstr "" +"`Odoo Multi-sociétés `_" + +#. module: connector +#: ../../index.rst:55 +msgid "" +"`Odoo Asynchronous import module `_" +msgstr "" +"`Module Odoo d'import asynchrone `_" + +#. module: connector +#: ../../index.rst:56 +msgid "`Salesforce Connector `_" +msgstr "`Connecteur Salesforce `_" + +#. module: connector +#: ../../index.rst:57 +msgid "" +"`Google Spreadsheet Connector `_" +msgstr "" +"`Connecteur Google Spreadsheet `_" + +#. module: connector +#: ../../index.rst:61 +msgid "" +"E-Commerce: Odoo OsCommerce connector, Odoo Drupal Commerce connector, Odoo " +"Spree connector, Odoo Ebay connector, Odoo Amazon connector…" +msgstr "" +"E-Commerce : connecteur Odoo OsCommerce, connecteur Odoo Drupal Commerce, " +"connecteur Odoo Spree, connecteur Odoo Ebay, connecteur Odoo Amazon…" + +#. module: connector +#: ../../index.rst:62 +msgid "CMS: Odoo Wordpress connector…" +msgstr "CMS : connecteur Odoo Wordpress…" + +#. module: connector +#: ../../index.rst:63 +msgid "CRM: Odoo SugarCRM connector, Odoo Zabbix connector…" +msgstr "CRM : connecteur Odoo SugarCRM, connecteur Odoo Zabbix…" + +#. module: connector +#: ../../index.rst:64 +msgid "Project Management: Odoo Redmine connector…" +msgstr "Gestion de projets : connecteur Odoo Redmine…" + +#. module: connector +#: ../../index.rst:65 +msgid "Ticketing: Odoo Request Tracker connector, Odoo GLPI connector…" +msgstr "Ticketing : connecteur Odoo Request Tracker, connecteur Odoo GLPI…" + +#~ msgid "Odoo Connector" +#~ msgstr "Odoo Connector" + +#~ msgid "" +#~ "Odoo Connector is a powerful framework to develop any kind of bi-" +#~ "directional connector between `Odoo`_ (Open Source ERP) and any other " +#~ "software or service." +#~ msgstr "" +#~ "`Odoo Connector` est un puissant framework de développement de " +#~ "connecteur bi-directionnel entre `Odoo`_ (ERP Open Source) et tout " +#~ "autre logiciel ou service." + +#~ msgid "" +#~ "This Odoo add-on has a modular and generic core, with the ability to " +#~ "be extended with additional modules for new features or customizations." +#~ msgstr "" +#~ "Ce module Odoo a un cœur modulaire et générique, capable d'être lui-" +#~ "même étendu grâce à des modules additionnels, pour ajouter des nouvelles " +#~ "fonctions ou des personnalisations." + +#~ msgid "" +#~ "The development of Odoo Connector has been started by `Camptocamp`_ " +#~ "and is now maintained by `Camptocamp`_, `Akretion`_ and several :ref:" +#~ "`contributors`." +#~ msgstr "" +#~ "Le développement du Connecteur Odoo a été démarré par `Camptocamp`_ et " +#~ "est maintenu par `Camptocamp`_, `Akretion`_ et d'autres :ref:" +#~ "`contributors`." + +#~ msgid "" +#~ "Not only designed to connect Odoo with e-commerce backends, rather it " +#~ "is **adaptable** to connect Odoo with any type of service." +#~ msgstr "" +#~ "Pas uniquement conçu pour connecter Odoo à des backend e-commerce, " +#~ "mais **adaptable** pour connecter Odoo à tout type de service." + +#~ msgid "" +#~ "`Odoo Multi Company `_" +#~ msgstr "" +#~ "`Odoo Multi-sociétés `_" + +#~ msgid "" +#~ "E-Commerce: Odoo OsCommerce connector, Odoo Drupal Commerce " +#~ "connector, Odoo Spree connector, Odoo Ebay connector, Odoo " +#~ "Amazon connector…" +#~ msgstr "" +#~ "E-Commerce : connecteur Odoo OsCommerce, connecteur Odoo Drupal " +#~ "Commerce, connecteur Odoo Spree, connecteur Odoo Ebay, connecteur " +#~ "Odoo Amazon…" + +#~ msgid "CMS: Odoo Wordpress connector…" +#~ msgstr "CMS : connecteur Odoo Wordpress…" + +#~ msgid "CRM: Odoo SugarCRM connector, Odoo Zabbix connector…" +#~ msgstr "CRM : connecteur Odoo SugarCRM, connecteur Odoo Zabbix…" + +#~ msgid "Project Management: Odoo Redmine connector…" +#~ msgstr "Gestion de projets : connecteur Odoo Redmine…" + +#~ msgid "" +#~ "Ticketing: Odoo Request Tracker connector, Odoo GLPI connector…" +#~ msgstr "" +#~ "Ticketing : connecteur Odoo Request Tracker, connecteur Odoo GLPI…" diff --git a/connector/doc/locale/fr/LC_MESSAGES/project.po b/connector/doc/locale/fr/LC_MESSAGES/project.po new file mode 100644 index 000000000..3864a338e --- /dev/null +++ b/connector/doc/locale/fr/LC_MESSAGES/project.po @@ -0,0 +1,909 @@ +# +msgid "" +msgstr "" +"Project-Id-Version: Connector\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-04-15 22:28+0300\n" +"PO-Revision-Date: 2015-05-05 11:48+0100\n" +"Last-Translator: Guewen Baconnier \n" +"Language-Team: fr \n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 1.5.4\n" + +#. module: connector +#: ../../project/changes.rst:5 +msgid "Changes" +msgstr "Changements" + +#. module: connector +#: ../../../CHANGES.rst:2 +msgid "3.0.0 (2015-04-01)" +msgstr "3.0.0 (2015-04-01)" + +#. module: connector +#: ../../../CHANGES.rst:4 +msgid "/!\\ Backwards incompatible changes inside." +msgstr "Attention : changements non rétro-compatibles dans cette version." + +#. module: connector +#: ../../../CHANGES.rst:6 +msgid "" +"Add ``odoo.api.Environment`` in ``Session`` It is accessible in ``self." +"env`` in ``Session`` and all ``ConnectorUnit`` instances. Also in " +"``ConnectorUnit``, ``model`` returns the current (new api!) model:" +msgstr "" +"Ajout de ``odoo.api.Environment`` dans ``Session`` Accessible via ``self." +"env`` dans ``Session`` et toutes les instances ``ConnectorUnit``. Également " +"dans ``ConnectorUnit``, ``model`` renvoie le modèle en cours (nouvelle " +"API!) :" + +#. module: connector +#: ../../../CHANGES.rst:20 +msgid "Deprecate the CRUD methods in ``Session``" +msgstr "Dépréciation des méthodes CRUD dans ``Session``" + +#. module: connector +#: ../../../CHANGES.rst:32 +msgid "" +"``Environment.set_lang()`` is removed. It was modifying the context in place " +"which is not possible with the new frozendict context. It should be done " +"with:" +msgstr "" +"``Environment.set_lang()`` est supprimé. Il modifiait le contexte sur place " +"ce qui n'est pas possible avec les nouveaux context en frozendict. Doit être " +"fait avec:" + +#. module: connector +#: ../../../CHANGES.rst:41 +msgid "Add an argument on the Binders methods to return a browse record" +msgstr "" +"Ajout d'un argument sur les méthodes des Binders pour renvoyer un `browse " +"record`" + +#. module: connector +#: ../../../CHANGES.rst:47 +msgid "" +"Shorten ``ConnectorUnit.get_binder_for_model`` to ``ConnectorUnit." +"binder_for``" +msgstr "" +"Renommage de ``ConnectorUnit.get_binder_for_model`` vers ``ConnectorUnit." +"binder_for``" + +#. module: connector +#: ../../../CHANGES.rst:49 +msgid "" +"Shorten ``ConnectorUnit.get_connector_unit_for_model`` to ``ConnectorUnit." +"unit_for``" +msgstr "" +"Renommage de ``ConnectorUnit.get_connector_unit_for_model`` vers " +"``ConnectorUnit.unit_for``" + +#. module: connector +#: ../../../CHANGES.rst:51 +msgid "" +"Renamed ``Environment`` to ``ConnectorEnvironment`` to avoid confusion with " +"``odoo.api.Environment``" +msgstr "" +"Renommage d'``Environment`` vers ``ConnectorEnvironment`` pour éviter la " +"confusion avec ``odoo.api.Environment``" + +#. module: connector +#: ../../../CHANGES.rst:53 +msgid "" +"Renamed the class attribute ``ConnectorUnit.model_name`` to ``ConnectorUnit." +"for_model_name``." +msgstr "" +"Renommage de l'attribut de classe ``ConnectorUnit.model_name`` vers " +"``ConnectorUnit.for_model_name``." + +#. module: connector +#: ../../../CHANGES.rst:55 +msgid "" +"Added ``_base_binder``, ``_base_mapper``, ``_base_backend_adapter`` in the " +"synchronizers (Importer, Exporter) so it is no longer required to override " +"the ``binder``, ``mapper``, ``backend_adapter`` property methods" +msgstr "" +"Ajout de ``_base_binder``, ``_base_mapper``, ``_base_backend_adapter`` dans " +"les synchroniseurs (Importer, Exporter) donc ce n'est plus nécessaire pour " +"surcharger les méthodes property ``binder``, ``mapper``, ``backend_adapter``" + +#. module: connector +#: ../../../CHANGES.rst:59 +msgid "" +"``Session.change_context()`` now supports the same argument/keyword " +"arguments semantics than ``odoo.model.BaseModel.with_context()``." +msgstr "" +"``Session.change_context()`` prend maintenant en charge la même sémantique " +"d'arguments que ``odoo.model.BaseModel.with_context()``." + +#. module: connector +#: ../../../CHANGES.rst:62 +msgid "Renamed ``ExportSynchronizer`` to ``Exporter``" +msgstr "Renommage de ``ExportSynchronizer`` vers ``Exporter``" + +#. module: connector +#: ../../../CHANGES.rst:63 +msgid "Renamed ``ImportSynchronizer`` to ``Importer``" +msgstr "Renommage de ``ImportSynchronizer`` vers ``Importer``" + +#. module: connector +#: ../../../CHANGES.rst:64 +msgid "Renamed ``DeleteSynchronizer`` to ``Deleter``" +msgstr "Renommage de ``DeleteSynchronizer`` vers ``Deleter``" + +#. module: connector +#: ../../../CHANGES.rst:65 +msgid "``Session.commit`` do not commit when tests are running" +msgstr "``Session.commit`` ne commite pas pendant les tests" + +#. module: connector +#: ../../../CHANGES.rst:66 +msgid "Cleaned the methods that have been deprecated in version 2.x" +msgstr "Nettoyage des méthodes dépréciées en version 2.x" + +#. module: connector +#: ../../../CHANGES.rst:70 +msgid "2.2.0 (2014-05-26)" +msgstr "2.2.0 (2014-05-26)" + +#. module: connector +#: ../../../CHANGES.rst:72 +msgid "" +"Job arguments can now contain unicode strings (thanks to Stéphane Bidoul) " +"lp:1288187" +msgstr "" +"Les arguments d'un Job peuvent maintenant contenir des chaînes unicode " +"(merci à Stéphane Bidoul) lp:1288187" + +#. module: connector +#: ../../../CHANGES.rst:73 +msgid "List view of the jobs improved" +msgstr "Amélioration de la vue en liste des jobs" + +#. module: connector +#: ../../../CHANGES.rst:74 +msgid "" +"Jobs now support multicompany (thanks to Laurent Mignon) https://lists." +"launchpad.net/odoo-connector-community/msg00253.html)" +msgstr "" +"Les jobs fonctionnement maintenant en multi-sociétés (merci à Laurent " +"Mignon) https://lists.launchpad.net/odoo-connector-community/msg00253." +"html)" + +#. module: connector +#: ../../../CHANGES.rst:75 +msgid "" +"An action can be assigned to a job. The action is called with a button on " +"the job and could be something like open a form view or an url." +msgstr "" +"Une action peut être affectée à un job. L'action est appelée via un bouton " +"sur le job et peut appeler une ouverture de formulaire ou une URL." + +#. module: connector +#: ../../../CHANGES.rst:78 +msgid "2.1.1 (2014-02-06)" +msgstr "2.1.1 (2014-02-06)" + +#. module: connector +#: ../../../CHANGES.rst:80 +msgid "" +"A user can be blocked because he has no access to the model queue.job when a " +"job has been delayed. The creation of a job is low level and should not be " +"restrained by the accesses of the user. (lp:1276182)" +msgstr "" +"Un utilisateur peut être bloqué s'il n'a pas accès au modèle queue.job quand " +"un job a été retardé. La création d'un job est à bas niveau et ne devrait " +"pas être contrainte par les accès de l'utilisateur. (lp:1276182)" + +#. module: connector +#: ../../../CHANGES.rst:85 +msgid "2.1.0 (2014-01-15 - warning: breaks compatibility)" +msgstr "2.1.0 (2014-01-15 - attention : rupture de compatibilité)" + +#. module: connector +#: ../../../CHANGES.rst:87 +msgid "" +"Add a new optional keyword argument 'description' to the delay() function of " +"a job. If given, the description is used as name of the queue.job record " +"stored in Odoo and displayed in the list of jobs." +msgstr "" +"Ajout d'un nouvel argument nommé 'description' pour la fonction delay() d'un " +"job. Si fournie, la description est utilisée comme nom pour " +"l'enregistrement ``queue.job`` stocké dans Odoo et affiché dans la liste " +"des jobs." + +#. module: connector +#: ../../../CHANGES.rst:90 +msgid "" +"Fix: assignment of jobs to workers respect the priority of the jobs " +"(lp:1252681)" +msgstr "" +"Correction: l'affectation des jobs aux workers respecte la priorité des jobs " +"(lp:1252681)" + +#. module: connector +#: ../../../CHANGES.rst:91 +msgid "" +"Pass a new parameter to listeners of 'on_record_create' ( vals: field " +"values of the new record, e.g {'field_name': field_value, ...})" +msgstr "" +"Passage d'un nouveau paramètre aux abonnés à 'on_record_create' ( vals: " +"valeurs du champ du nouvel enregistrement, par ex : {'field_name': " +"field_value, ...})" + +#. module: connector +#: ../../../CHANGES.rst:93 +msgid "" +"Replace the list of updated fields passed to listeners of 'on_record_write' " +"by a dictionary of updated field values e.g {'field_name': field_value, ...}" +msgstr "" +"Remplacement de la liste des champs modifiés transmis aux abonnés à " +"'on_record_write' par un dictionnaire des valeurs des champs modifiés. Par " +"ex : {'field_name': field_value, ...}" + +#. module: connector +#: ../../../CHANGES.rst:95 +msgid "" +"Add the possibility to use 'Modifiers' functions in the 'direct " +"mappings' (details in the documentation of the Mapper class)" +msgstr "" +"Ajout de la possibilité d'utiliser des fonctions 'Modificatrices' dans les " +"'mappings directs' (détails dans la documentation de la classe Mapper)" + +#. module: connector +#: ../../../CHANGES.rst:97 +msgid "" +"When a job a delayed, the job's UUID is returned by the delay() function" +msgstr "" +"Quand un job est retardé, le UUID du job est renvoyé par la fonction delay()" + +#. module: connector +#: ../../../CHANGES.rst:98 +msgid "" +"Refactoring of mappers. Much details here: https://code.launchpad.net/" +"~odoo-connector-core-editors/odoo-connector/7.0-connector-mapper-" +"refactor/+merge/194485" +msgstr "" +"Refactorisation des mappers. Plus de détails ici : https://code.launchpad." +"net/~odoo-connector-core-editors/odoo-connector/7.0-connector-mapper-" +"refactor/+merge/194485" + +#. module: connector +#: ../../../CHANGES.rst:102 +msgid "2.0.1 (2013-09-12)" +msgstr "2.0.1 (2013-09-12)" + +#. module: connector +#: ../../../CHANGES.rst:104 +msgid "" +"Developers of addons do no longer need to create an AbstractModel with a " +"_name 'name_of_the_module.installed', instead, they just have to call " +"connector.connector.install_in_connector() lp:1196859" +msgstr "" +"Les développeurs d'addons n'ont plus besoin de créer un AbstractModel avec " +"un _name 'nom_module.installed', ils doivent simplement appeler ``connector." +"connector.install_in_connector()`` lp:1196859" + +#. module: connector +#: ../../../CHANGES.rst:106 +msgid "" +"Added a script `odoo-connector-worker` to start processes for Jobs " +"Workers when running Odoo is multiprocessing" +msgstr "" +"Ajout d'un script `odoo-connector-worker` pour lancer les processus des " +"workers de jobs en fonctionnement multi-processus d'Odoo" + +#. module: connector +#: ../../../CHANGES.rst:108 +msgid "" +"Fix: do no fail to start when Odoo has access to a not-Odoo database " +"(lp:1233388)" +msgstr "" +"Correction : n'échoue pas au démarrage quand Odoo a accès à une base de " +"données non-Odoo (lp:1233388)" + +#. module: connector +#: ../../../CHANGES.rst:112 +msgid "2.0.0" +msgstr "2.0.0" + +#. module: connector +#: ../../../CHANGES.rst:114 +msgid "First release" +msgstr "Première version" + +#. module: connector +#: ../../project/contribute.rst:5 +msgid "Contribute" +msgstr "Contribuer" + +#. module: connector +#: ../../project/contribute.rst:7 +msgid "We accept with pleasure all type of contributions:" +msgstr "Nous acceptons avec plaisir tous types de contributions :" + +#. module: connector +#: ../../project/contribute.rst:9 +msgid "bug reports" +msgstr "Signalement d'anomalies" + +#. module: connector +#: ../../project/contribute.rst:10 +msgid "merge proposals" +msgstr "Propositions de corrections" + +#. module: connector +#: ../../project/contribute.rst:11 +msgid "ideas" +msgstr "idées" + +#. module: connector +#: ../../project/contribute.rst:12 +msgid "translations" +msgstr "traductions" + +#. module: connector +#: ../../project/contribute.rst:13 +msgid "..." +msgstr "..." + +#. module: connector +#: ../../project/contribute.rst:15 +msgid "" +"Have a look on the :ref:`Magento Connector Developer's Guide " +"` which is more complete, most of the " +"information is the same." +msgstr "" +"Jetez un œil au :ref:`Guide du développeur du Connecteur Magento " +"` qui est plus complet, la plupart des " +"informations sont les mêmes." + +#. module: connector +#: ../../project/contribute.rst:19 +msgid "The GitHub project is: https://github.com/OCA/connector" +msgstr "Le projet GitHub est : https://github.com/OCA/connector" + +#. module: connector +#: ../../project/contribute.rst:23 +msgid "Want to start a new connector" +msgstr "Démarrer un nouveau connecteur" + +#. module: connector +#: ../../project/contribute.rst:25 +msgid "" +"If you want to start a new connector based on the framework, a sane approach " +"is to read this documentation, especially :ref:`concepts` and :ref:" +"`bootstrap-connector`." +msgstr "" +"Si vous voulez fabriquer un nouveau connecteur basé sur le framework, " +"l'approche conseillée est de lire cette documentation, en particulier les :" +"ref:`concepts` et :ref:`bootstrap-connector`." + +#. module: connector +#: ../../project/contribute.rst:33 +msgid "" +"If the connector belongs to the e-commerce domain, you may want to reuse the " +"pieces of the `E-Commerce Connector`_ module." +msgstr "" +"Si le connecteur est dans le domaine e-commerce, vous devriez réutiliser les " +"composants du module `E-Commerce Connector`_." + +#. module: connector +#: ../../project/contribute.rst:39 +msgid "Naming conventions" +msgstr "Conventions de nommage" + +#. module: connector +#: ../../project/contribute.rst:41 +msgid "The naming conventions for the new projects are the following:" +msgstr "" +"Les conventions de nommage pour les nouveaux projets sont les suivantes :" + +#. module: connector +#: ../../project/contribute.rst:43 +msgid "Name of the project if it is in the OCA:" +msgstr "Nom du projet s'il est dans l'OCA :" + +#. module: connector +#: ../../project/contribute.rst:45 +msgid "connector-xxx" +msgstr "connector-xxx" + +#. module: connector +#: ../../project/contribute.rst:48 +msgid "connector_xxx" +msgstr "connector_xxx" + +#. module: connector +#: ../../project/contribute.rst:53 +msgid "Example:" +msgstr "Exemple :" + +#. module: connector +#: ../../project/contribute.rst:51 +msgid "https://github.com/OCA/connector-magento" +msgstr "https://github.com/OCA/connector-magento" + +#. module: connector +#: ../../project/contribute.rst:53 +msgid "``connector_magento``" +msgstr "``connector_magento``" + +#. module: connector +#: ../../project/contribute.rst:55 +msgid "" +"Actually, the Magento and Prestashop connectors do not respect this " +"convention for historical reasons (magentoerpconnect, prestashoperpconnect). " +"New projects should ideally respect it." +msgstr "" +"En réalité les connecteurs Magento et Prestashop ne respectent pas cette " +"convention pour des raisons historiques (magentoerpconnect, " +"prestashoperpconnect). Les nouveaux projets devraient idéalement la " +"respecter." + +#. module: connector +#: ../../project/contributors.rst:5 +msgid "Contributors" +msgstr "Contributeurs" + +#. module: connector +#: ../../project/contributors.rst:7 +msgid "List of contributors:" +msgstr "Liste des contributeurs :" + +#. module: connector +#: ../../../AUTHORS:1 +msgid "Guewen Baconnier at Camptocamp" +msgstr "Guewen Baconnier chez Camptocamp" + +#. module: connector +#: ../../../AUTHORS:2 +msgid "Alexandre Fayolle at Camptocamp" +msgstr "Alexandre Fayolle chez Camptocamp" + +#. module: connector +#: ../../../AUTHORS:3 +msgid "Benoit Guillot at Akretion" +msgstr "Benoit Guillot chez Akretion" + +#. module: connector +#: ../../../AUTHORS:4 +msgid "Nicolas Bessi at Camptocamp (tiny change)" +msgstr "Nicolas Bessi chez Camptocamp (changement minuscule)" + +#. module: connector +#: ../../../AUTHORS:5 +msgid "Joël Grand-Guillaume at Camptocamp (tiny change)" +msgstr "Joël Grand-Guillaume chez Camptocamp (changement minuscule)" + +#. module: connector +#: ../../../AUTHORS:6 +msgid "Arthur Vuillard at Akretion (tiny change)" +msgstr "Arthur Vuillard chez Akretion (changement minuscule)" + +#. module: connector +#: ../../../AUTHORS:7 +msgid "Sebastien Beau at Akretion (tiny change)" +msgstr "Sebastien Beau chez Akretion (changement minuscule)" + +#. module: connector +#: ../../../AUTHORS:8 +msgid "Laurent Mignon at Acsone" +msgstr "Laurent Mignon chez Acsone" + +#. module: connector +#: ../../../AUTHORS:9 +msgid "Leonardo Pistone at Camptocamp" +msgstr "Leonardo Pistone chez Camptocamp" + +#. module: connector +#: ../../../AUTHORS:10 +msgid "David Béal at Akretion (tiny change)" +msgstr "David Béal chez Akretion (changement minuscule)" + +#. module: connector +#: ../../project/contributors.rst:16 +msgid "Financial Contributors" +msgstr "Contributeurs financiers" + +#. module: connector +#: ../../project/contributors.rst:18 +msgid "" +"A fund raising has been done during the year 2013, allowing us to develop " +"the connector framework and the Magento connector." +msgstr "" +"Une levée de fond a été réalisée en 2013, et a permis de développer le " +"framework Connecteur et le Connecteur Magento." + +#. module: connector +#: ../../project/contributors.rst:21 +msgid "" +"Here is the list of the funders, ordered by the amount of the contribution:" +msgstr "Voici la liste des fondateurs, classée par volume de contribution :" + +#. module: connector +#: ../../project/contributors.rst:23 +msgid "**Logic Supply**" +msgstr "**Logic Supply**" + +#. module: connector +#: ../../project/contributors.rst:24 +msgid "**Debonix**" +msgstr "**Debonix**" + +#. module: connector +#: ../../project/contributors.rst:25 +msgid "Apertoso" +msgstr "Apertoso" + +#. module: connector +#: ../../project/contributors.rst:26 +msgid "OpenBIG" +msgstr "OpenBIG" + +#. module: connector +#: ../../project/contributors.rst:27 +msgid "Smile" +msgstr "Smile" + +#. module: connector +#: ../../project/contributors.rst:28 +msgid "IT Service Partners" +msgstr "IT Service Partners" + +#. module: connector +#: ../../project/contributors.rst:29 +msgid "WillowIT" +msgstr "WillowIT" + +#. module: connector +#: ../../project/contributors.rst:30 +msgid "Eezee-It" +msgstr "Eezee-It" + +#. module: connector +#: ../../project/contributors.rst:31 +msgid "Auguria" +msgstr "Auguria" + +#. module: connector +#: ../../project/contributors.rst:32 +msgid "Enova" +msgstr "Enova" + +#. module: connector +#: ../../project/contributors.rst:33 +msgid "Mr. Goran Sunjka" +msgstr "M. Goran Sunjka" + +#. module: connector +#: ../../project/contributors.rst:34 +msgid "Taktik" +msgstr "Taktik" + +#. module: connector +#: ../../project/contributors.rst:35 +msgid "Maison del Gusto" +msgstr "Maison del Gusto" + +#. module: connector +#: ../../project/contributors.rst:36 +msgid "Open2bizz Software" +msgstr "Open2bizz Software" + +#. module: connector +#: ../../project/contributors.rst:37 +msgid "Bee Company" +msgstr "Bee Company" + +#. module: connector +#: ../../project/contributors.rst:38 +msgid "initOS" +msgstr "initOS" + +#. module: connector +#: ../../project/contributors.rst:39 +msgid "Rhônalia" +msgstr "Rhônalia" + +#. module: connector +#: ../../project/contributors.rst:40 +msgid "Julius Network Solutions" +msgstr "Julius Network Solutions" + +#. module: connector +#: ../../project/contributors.rst:41 +msgid "Elico Corp" +msgstr "Elico Corp" + +#. module: connector +#: ../../project/contributors.rst:42 +msgid "Linko Solutions" +msgstr "Linko Solutions" + +#. module: connector +#: ../../project/contributors.rst:43 +msgid "HSP Hanse Shopping" +msgstr "HSP Hanse Shopping" + +#. module: connector +#: ../../project/contributors.rst:44 +msgid "Burn Out Italy" +msgstr "Burn Out Italy" + +#. module: connector +#: ../../project/contributors.rst:45 +msgid "Mr. Peter Dijkstra" +msgstr "M. Peter Dijkstra" + +#. module: connector +#: ../../project/contributors.rst:46 +msgid "Mr. Luc Maurer" +msgstr "M. Luc Maurer" + +#. module: connector +#: ../../project/contributors.rst:47 +msgid "Mr. Maxime Chambreuil" +msgstr "M. Maxime Chambreuil" + +#. module: connector +#: ../../project/contributors.rst:48 +msgid "Mr. Eric Vernichon" +msgstr "M. Eric Vernichon" + +#. module: connector +#: ../../project/contributors.rst:49 +msgid "Avanzosc" +msgstr "Avanzosc" + +#. module: connector +#: ../../project/contributors.rst:50 +msgid "Mr. Fabio Martinelli" +msgstr "M. Fabio Martinelli" + +#. module: connector +#: ../../project/contributors.rst:51 +msgid "Mr. Marcelo Bello" +msgstr "M. Marcelo Bello" + +#. module: connector +#: ../../project/contributors.rst:52 +msgid "Rove.design" +msgstr "Rove.design" + +#. module: connector +#: ../../project/contributors.rst:53 +msgid "Mr. Mark Felling" +msgstr "M. Mark Felling" + +#. module: connector +#: ../../project/contributors.rst:55 +msgid "Thanks to all of them!" +msgstr "Merci à eux !" + +#. module: connector +#: ../../project/license.rst:5 +msgid "License" +msgstr "Licence" + +#. module: connector +#: ../../project/license.rst:7 +msgid "This work is licensed under the LGPL3 license." +msgstr "Ce travail est publié sous licence LGPL3." + +#. module: connector +#: ../../project/roadmap.rst:5 +msgid "Roadmap" +msgstr "Roadmap" + +#. module: connector +#: ../../project/roadmap.rst:7 +msgid "Here is a list of things we may agree to merge." +msgstr "Voici une liste de choses qu'on peut s'accorder à intégrer" + +#. module: connector +#: ../../project/roadmap.rst:9 +msgid "Queue: use PostgreSQL `notify` for direct enqueue of jobs" +msgstr "" +"Queue : utiliser `notify` de PostgreSQL pour une mise en queue directe des " +"jobs" + +#. module: connector +#: ../../project/roadmap.rst:13 +msgid "" +"Add facilities to parse the errors from the jobs so we can replace it by " +"more contextual and helpful errors." +msgstr "" +"Ajouter des facilités pour analyser les erreurs des jobs pour pouvoir les " +"remplacer par des erreurs plus contextuelles et utiles" + +#. module: connector +#: ../../project/roadmap.rst:16 +msgid "" +"A logger which keeps in a buffer all the logs and flushes them when an error " +"occurs in a synchronization, clears them if it succeeded" +msgstr "" +"Un `logger` qui garde en tampon tous les logs et les vide quand une erreur " +"survient pendant une synchronisation, et les efface s'ils ont réussi" + +#. module: connector +#: ../../project/roadmap.rst:19 +msgid "" +"Job Channels: each job is owned by a channel and workers can be dedicated to " +"one channel only" +msgstr "" +"Canal de job : chaque job appartient à un canal et les workers peuvent être " +"dédiés à un canal" + +#. module: connector +#: ../../../CHANGES.rst:107 +msgid "" +"Fix: inheritance broken when an orm.Model inherit from an orm.AbstractModel. " +"One effect was that the mail.thread features were no longer working " +"(lp:1233355)" +msgstr "" +"Correction : héritage cassé quand un orm.Model hérite d'un orm." +"AbstractModel. Un effet était que les fonctionnalités de mail.thread ne " +"fonctionnaient plus (lp:1233355)" + +#. module: connector +#: ../../../AUTHORS:11 +msgid "Christophe Combelles at Anybox (french translation)" +msgstr "Christophe Combelles chez Anybox (trad française)" + +#. module: connector +#: ../../project/contribute.rst:65 +msgid "Creating or maintaining a translation of this doc" +msgstr "Créer ou maintenir une traduction de cette doc" + +#. module: connector +#: ../../project/contribute.rst:67 +msgid "" +"Install Odoo, its dependencies, sphinx, sphinx_bootstrap_theme and sphinx-" +"intl" +msgstr "" +"Installez Odoo, ses dépendances, sphinx, sphinx_bootstrap_theme et sphinx-" +"intl" + +#. module: connector +#: ../../project/contribute.rst:72 +msgid "create an empty database with the connector module installed" +msgstr "créez une nouvelle base de donnée avec le module connector installé" + +#. module: connector +#: ../../project/contribute.rst:73 +msgid "``cd connector/doc``" +msgstr "``cd connector/doc``" + +#. module: connector +#: ../../project/contribute.rst:74 +msgid "rebuild the gettext .pot source catalogs: ``make gettext``" +msgstr "reconstruisez les catalogues gettext sources .pot: ``make gettext``" + +#. module: connector +#: ../../project/contribute.rst:75 +msgid "" +"update the .po translation files from the latest .pot files (here for " +"language 'fr'): ``sphinx-intl update -l fr -p _build/locale``" +msgstr "" +"mettez à jour les fichiers de traduction .po depuis les derniers fichiers ." +"pot (ici pour la langue 'fr'): ``sphinx-intl update -l fr -p _build/locale``" + +#. module: connector +#: ../../project/contribute.rst:77 +msgid "" +"create or edit the translation in the .po files: ``poedit locale/fr/" +"LC_MESSAGES/*.po``" +msgstr "" +"créez ou modifiez la traduction dans les fichiers .po : ``poedit locale/fr/" +"LC_MESSAGES/*.po``" + +#. module: connector +#: ../../project/contribute.rst:79 +msgid "compile the .po files into .mo files: ``sphinx-intl build``" +msgstr "compilez les fichiers .po en fichiers .mo : ``sphinx-intl build``" + +#. module: connector +#: ../../project/contribute.rst:80 +msgid "" +"build the translated documentation to html: ``make SPHINXOPTS=\"-Dlanguage=fr" +"\" html``" +msgstr "" +"construisez en html la documentation traduite : ``make SPHINXOPTS=\"-" +"Dlanguage=fr\" html``" + +#. module: connector +#: ../../project/contribute.rst:83 +msgid "" +"The same using a `buildout `_::" +msgstr "" +"La même chose en utilisant un `buildout `_::" + +#. module: connector +#: ../../project/contribute.rst:69 +msgid "" +"Add `this patch `_ to sphinx-intl (until merged) to support *fuzzy* translations" +msgstr "" +"Ajoutez `ce patch `_ à sphinx-intl (jusqu'à ce que ce soit mergé) pour gérer les " +"traductions *fuzzy*" + +#. module: connector +#: ../../project/contribute.rst:29 +msgid "" +"Then, my personal advice is to look at the existing connectors (`Odoo " +"Magento Connector`_, `Odoo Prestashop Connector`_). You will also probably " +"need to dive a bit in the framework's code." +msgstr "" +"Ensuite, il est conseillé de parcourir les connecteurs existants " +"(`Connecteur Odoo Magento`_, `Connecteur Odoo Prestashop`_). Vous devrez " +"aussi plonger peut-être un peu dans le code du framework." + +#. module: connector +#: ../../project/contribute.rst:48 +msgid "Name of the Odoo module:" +msgstr "Nom du module Odoo :" + +#. module: connector +#: ../../project/contribute.rst:100 +msgid "" +"Then you can see the result in _build/html/ and submit a Pull Request. " +"Repeat the 5 last steps to update the translation if modified upstream." +msgstr "" +"Vous pouvez ensuite voir le résultat dans _build/html/ et soumettre un " +"\"Pull Request\". Répétez les 5 dernières étapes pour remettre à jour les " +"traductions en cas de modification dans le tronc principal." + +#. module: connector +#: ../../project/roadmap.rst:11 ../../project/roadmap.rst:22 +msgid "See: https://github.com/OCA/connector/pull/52" +msgstr "See: https://github.com/OCA/connector/pull/52" + +#~ msgid "" +#~ "Then, my personal advice is to look at the existing connectors (`Odoo " +#~ "Magento Connector`_, `Odoo Prestashop Connector`_). You will also " +#~ "probably need to dive a bit in the framework's code." +#~ msgstr "" +#~ "Ensuite, il est conseillé de parcourir les connecteurs existants " +#~ "(`Connecteur Odoo Magento`_, `Connecteur Odoo Prestashop`_). Vous " +#~ "devrez aussi plonger peut-être un peu dans le code du framework." + +#~ msgid "Name of the Odoo module:" +#~ msgstr "Nom du module Odoo :" + +#~ msgid "" +#~ "Experimental branch: lp:~odoo-connector-core-editors/odoo-" +#~ "connector/7.0-connector-pg-notify-listen-experimental" +#~ msgstr "" +#~ "Branche expérimentale : lp:~odoo-connector-core-editors/odoo-" +#~ "connector/7.0-connector-pg-notify-listen-experimental" + +#~ msgid "" +#~ "Then you can see the result in _build/html/ and submit a Pull Request" +#~ msgstr "" +#~ "Vous pouvez ensuite voir le résultat dans _build/html/ et soumettre un " +#~ "Pull Request" + +#~ msgid "" +#~ "Add `this patch `_ to sphinx-intl (until " +#~ "merged)" +#~ msgstr "" +#~ "Ajoutez `ce patch `_ to sphinx-intl (jusqu'à " +#~ "ce qu'il soit mergé)" + +#~ msgid "" +#~ "Fix: inheritance broken when an orm.Model inherit from an or." +#~ "AbstractModel. One effect was that the mail.thread features were no " +#~ "longer working (lp:1233355)" +#~ msgstr "" +#~ "Correction : héritage cassé quand un orm.Model hérite d'un or." +#~ "AbstractModel. Une conséquence est que les fonctionnalités de mail.thread " +#~ "ne fonctionnaient plus (lp:1233355)" diff --git a/connector/doc/make.bat b/connector/doc/make.bat new file mode 100644 index 000000000..3b846632a --- /dev/null +++ b/connector/doc/make.bat @@ -0,0 +1,190 @@ +@ECHO OFF + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set BUILDDIR=_build +set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . +set I18NSPHINXOPTS=%SPHINXOPTS% . +if NOT "%PAPER%" == "" ( + set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% + set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% +) + +if "%1" == "" goto help + +if "%1" == "help" ( + :help + echo.Please use `make ^` where ^ is one of + echo. html to make standalone HTML files + echo. dirhtml to make HTML files named index.html in directories + echo. singlehtml to make a single large HTML file + echo. pickle to make pickle files + echo. json to make JSON files + echo. htmlhelp to make HTML files and a HTML help project + echo. qthelp to make HTML files and a qthelp project + echo. devhelp to make HTML files and a Devhelp project + echo. epub to make an epub + echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter + echo. text to make text files + echo. man to make manual pages + echo. texinfo to make Texinfo files + echo. gettext to make PO message catalogs + echo. changes to make an overview over all changed/added/deprecated items + echo. linkcheck to check all external links for integrity + echo. doctest to run all doctests embedded in the documentation if enabled + goto end +) + +if "%1" == "clean" ( + for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i + del /q /s %BUILDDIR%\* + goto end +) + +if "%1" == "html" ( + %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/html. + goto end +) + +if "%1" == "dirhtml" ( + %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. + goto end +) + +if "%1" == "singlehtml" ( + %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. + goto end +) + +if "%1" == "pickle" ( + %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the pickle files. + goto end +) + +if "%1" == "json" ( + %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the JSON files. + goto end +) + +if "%1" == "htmlhelp" ( + %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run HTML Help Workshop with the ^ +.hhp project file in %BUILDDIR%/htmlhelp. + goto end +) + +if "%1" == "qthelp" ( + %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run "qcollectiongenerator" with the ^ +.qhcp project file in %BUILDDIR%/qthelp, like this: + echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Connectors.qhcp + echo.To view the help file: + echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Connectors.ghc + goto end +) + +if "%1" == "devhelp" ( + %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. + goto end +) + +if "%1" == "epub" ( + %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The epub file is in %BUILDDIR%/epub. + goto end +) + +if "%1" == "latex" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "text" ( + %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The text files are in %BUILDDIR%/text. + goto end +) + +if "%1" == "man" ( + %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The manual pages are in %BUILDDIR%/man. + goto end +) + +if "%1" == "texinfo" ( + %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. + goto end +) + +if "%1" == "gettext" ( + %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The message catalogs are in %BUILDDIR%/locale. + goto end +) + +if "%1" == "changes" ( + %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes + if errorlevel 1 exit /b 1 + echo. + echo.The overview file is in %BUILDDIR%/changes. + goto end +) + +if "%1" == "linkcheck" ( + %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck + if errorlevel 1 exit /b 1 + echo. + echo.Link check complete; look for any errors in the above output ^ +or in %BUILDDIR%/linkcheck/output.txt. + goto end +) + +if "%1" == "doctest" ( + %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest + if errorlevel 1 exit /b 1 + echo. + echo.Testing of doctests in the sources finished, look at the ^ +results in %BUILDDIR%/doctest/output.txt. + goto end +) + +:end diff --git a/connector/doc/project/contribute.rst b/connector/doc/project/contribute.rst new file mode 100644 index 000000000..fd47353a9 --- /dev/null +++ b/connector/doc/project/contribute.rst @@ -0,0 +1,100 @@ +.. _contribute: + +########## +Contribute +########## + +We accept with pleasure all type of contributions: + +* bug reports +* merge proposals +* ideas +* translations +* ... + +Have a look on the :ref:`Magento Connector Developer's Guide +` which is more complete, most of the +information is the same. + +The GitHub project is: https://github.com/OCA/connector + +***************************** +Want to start a new connector +***************************** + +If you want to start a new connector based on the framework, +a sane approach is to read this documentation, especially +:ref:`concepts` and :ref:`bootstrap-connector`. + +Then, my personal advice is to look at the existing connectors (`Odoo +Magento Connector`_, `Odoo Prestashop Connector`_). You will also probably +need to dive a bit in the framework's code. + +If the connector belongs to the e-commerce domain, you may want to reuse the pieces +of the `E-Commerce Connector`_ module. + +.. _naming-convention: + +Naming conventions +================== + +The naming conventions for the new projects are the following: + +Name of the project if it is in the OCA: + + connector-xxx + +Name of the Odoo module: + connector_xxx + +Example: + https://github.com/OCA/connector-magento + + ``connector_magento`` + +Actually, the Magento and Prestashop connectors do not respect this convention +for historical reasons (magentoerpconnect, prestashoperpconnect). +New projects should ideally respect it. + +.. _`Odoo Magento Connector`: https://github.com/OCA/connector-magento +.. _`Odoo Prestashop Connector`: https://github.com/OCA/connector-prestashop +.. _`E-Commerce Connector`: https://github.com/OCA/connector-ecommerce + +************************************************* +Creating or maintaining a translation of this doc +************************************************* + +- Install Odoo, its dependencies, sphinx, sphinx_bootstrap_theme and + sphinx-intl +- Add `this patch + `_ + to sphinx-intl (until merged) to support *fuzzy* translations +- create an empty database with the connector module installed +- ``cd connector/doc`` +- rebuild the gettext .pot source catalogs: ``make gettext`` +- update the .po translation files from the latest .pot files (here for + language 'fr'): ``sphinx-intl update -l fr -p _build/locale`` +- create or edit the translation in the .po files: ``poedit + locale/fr/LC_MESSAGES/*.po`` +- compile the .po files into .mo files: ``sphinx-intl build`` +- build the translated documentation to html: ``make SPHINXOPTS="-Dlanguage=fr" + html`` + +The same using a `buildout +`_:: + + $ mkdir buildout && cd buildout + $ wget https://bitbucket.org/anybox/public_buildbot_buildouts/raw/tip/odoo-connector.cfg -O buildout.cfg + $ wget https://bitbucket.org/anybox/public_buildbot_buildouts/raw/tip/bootstrap.py + $ python bootstrap.py + $ bin/buildout + $ createdb connectordb + $ bin/start_odoo -d connectordb --stop-after-init + $ cd connector/connector/doc/ + $ ../../../bin/sphinx-build -d connectordb -- -b gettext ./ _build/locale/ + $ ../../../bin/sphinx-intl -d connectordb -- update -l fr -p _build/locale/ + $ poedit locale/fr/LC_MESSAGES/*po + $ ../../../bin/sphinx-intl -d connectordb -- build + $ ../../../bin/sphinx-build -d connectordb -- -D language=fr -b html ./ _build/html/ + +Then you can see the result in _build/html/ and submit a Pull Request. Repeat the 5 last steps to update the translation if modified upstream. diff --git a/connector/doc/project/contributors.rst b/connector/doc/project/contributors.rst new file mode 100644 index 000000000..a115cdf24 --- /dev/null +++ b/connector/doc/project/contributors.rst @@ -0,0 +1,55 @@ +.. _contributors: + +############ +Contributors +############ + +List of contributors: + +.. include:: ../../AUTHORS + + +.. _financial-contributors: + +###################### +Financial Contributors +###################### + +A fund raising has been done during the year 2013, allowing us to develop +the connector framework and the Magento connector. + +Here is the list of the funders, ordered by the amount of the contribution: + +* **Logic Supply** +* **Debonix** +* Apertoso +* OpenBIG +* Smile +* IT Service Partners +* WillowIT +* Eezee-It +* Auguria +* Enova +* Mr. Goran Sunjka +* Taktik +* Maison del Gusto +* Open2bizz Software +* Bee Company +* initOS +* Rhônalia +* Julius Network Solutions +* Elico Corp +* Linko Solutions +* HSP Hanse Shopping +* Burn Out Italy +* Mr. Peter Dijkstra +* Mr. Luc Maurer +* Mr. Maxime Chambreuil +* Mr. Eric Vernichon +* Avanzosc +* Mr. Fabio Martinelli +* Mr. Marcelo Bello +* Rove.design +* Mr. Mark Felling + +Thanks to all of them! diff --git a/connector/doc/project/license.rst b/connector/doc/project/license.rst new file mode 100644 index 000000000..0cd15bd16 --- /dev/null +++ b/connector/doc/project/license.rst @@ -0,0 +1,674 @@ +.. _license: + +####### +License +####### + +This work is licensed under the LGPL3 license. + +------ + +.. code-block:: none + + + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for + software and other kinds of works, specifically designed to ensure + cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed + to take away your freedom to share and change the works. By contrast, + our General Public Licenses are intended to guarantee your freedom to + share and change all versions of a program--to make sure it remains free + software for all its users. + + When we speak of free software, we are referring to freedom, not + price. Our General Public Licenses are designed to make sure that you + have the freedom to distribute copies of free software (and charge for + them if you wish), that you receive source code or can get it if you + want it, that you can change the software or use pieces of it in new + free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights + with two steps: (1) assert copyright on the software, and (2) offer + you this License which gives you legal permission to copy, distribute + and/or modify the software. + + A secondary benefit of defending all users' freedom is that + improvements made in alternate versions of the program, if they + receive widespread use, become available for other developers to + incorporate. Many developers of free software are heartened and + encouraged by the resulting cooperation. However, in the case of + software used on network servers, this result may fail to come about. + The GNU General Public License permits making a modified version and + letting the public access it on a server without ever releasing its + source code to the public. + + The GNU Affero General Public License is designed specifically to + ensure that, in such cases, the modified source code becomes available + to the community. It requires the operator of a network server to + provide the source code of the modified version running there to the + users of that server. Therefore, public use of a modified version, on + a publicly accessible server, gives the public access to the source + code of the modified version. + + An older license, called the Affero General Public License and + published by Affero, was designed to accomplish similar goals. This is + a different license, not a version of the Affero GPL, but Affero has + released a new version of the Affero GPL which permits relicensing under + this license. + + The precise terms and conditions for copying, distribution and + modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of + works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this + License. Each licensee is addressed as "you". "Licensees" and + "recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work + in a fashion requiring copyright permission, other than the making of an + exact copy. The resulting work is called a "modified version" of the + earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based + on the Program. + + To "propagate" a work means to do anything with it that, without + permission, would make you directly or secondarily liable for + infringement under applicable copyright law, except executing it on a + computer or modifying a private copy. Propagation includes copying, + distribution (with or without modification), making available to the + public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other + parties to make or receive copies. Mere interaction with a user through + a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" + to the extent that it includes a convenient and prominently visible + feature that (1) displays an appropriate copyright notice, and (2) + tells the user that there is no warranty for the work (except to the + extent that warranties are provided), that licensees may convey the + work under this License, and how to view a copy of this License. If + the interface presents a list of user commands or options, such as a + menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work + for making modifications to it. "Object code" means any non-source + form of a work. + + A "Standard Interface" means an interface that either is an official + standard defined by a recognized standards body, or, in the case of + interfaces specified for a particular programming language, one that + is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other + than the work as a whole, that (a) is included in the normal form of + packaging a Major Component, but which is not part of that Major + Component, and (b) serves only to enable use of the work with that + Major Component, or to implement a Standard Interface for which an + implementation is available to the public in source code form. A + "Major Component", in this context, means a major essential component + (kernel, window system, and so on) of the specific operating system + (if any) on which the executable work runs, or a compiler used to + produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all + the source code needed to generate, install, and (for an executable + work) run the object code and to modify the work, including scripts to + control those activities. However, it does not include the work's + System Libraries, or general-purpose tools or generally available free + programs which are used unmodified in performing those activities but + which are not part of the work. For example, Corresponding Source + includes interface definition files associated with source files for + the work, and the source code for shared libraries and dynamically + linked subprograms that the work is specifically designed to require, + such as by intimate data communication or control flow between those + subprograms and other parts of the work. + + The Corresponding Source need not include anything that users + can regenerate automatically from other parts of the Corresponding + Source. + + The Corresponding Source for a work in source code form is that + same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of + copyright on the Program, and are irrevocable provided the stated + conditions are met. This License explicitly affirms your unlimited + permission to run the unmodified Program. The output from running a + covered work is covered by this License only if the output, given its + content, constitutes a covered work. This License acknowledges your + rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not + convey, without conditions so long as your license otherwise remains + in force. You may convey covered works to others for the sole purpose + of having them make modifications exclusively for you, or provide you + with facilities for running those works, provided that you comply with + the terms of this License in conveying all material for which you do + not control copyright. Those thus making or running the covered works + for you must do so exclusively on your behalf, under your direction + and control, on terms that prohibit them from making any copies of + your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under + the conditions stated below. Sublicensing is not allowed; section 10 + makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological + measure under any applicable law fulfilling obligations under article + 11 of the WIPO copyright treaty adopted on 20 December 1996, or + similar laws prohibiting or restricting circumvention of such + measures. + + When you convey a covered work, you waive any legal power to forbid + circumvention of technological measures to the extent such circumvention + is effected by exercising rights under this License with respect to + the covered work, and you disclaim any intention to limit operation or + modification of the work as a means of enforcing, against the work's + users, your or third parties' legal rights to forbid circumvention of + technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you + receive it, in any medium, provided that you conspicuously and + appropriately publish on each copy an appropriate copyright notice; + keep intact all notices stating that this License and any + non-permissive terms added in accord with section 7 apply to the code; + keep intact all notices of the absence of any warranty; and give all + recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, + and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to + produce it from the Program, in the form of source code under the + terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent + works, which are not by their nature extensions of the covered work, + and which are not combined with it such as to form a larger program, + in or on a volume of a storage or distribution medium, is called an + "aggregate" if the compilation and its resulting copyright are not + used to limit the access or legal rights of the compilation's users + beyond what the individual works permit. Inclusion of a covered work + in an aggregate does not cause this License to apply to the other + parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms + of sections 4 and 5, provided that you also convey the + machine-readable Corresponding Source under the terms of this License, + in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded + from the Corresponding Source as a System Library, need not be + included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any + tangible personal property which is normally used for personal, family, + or household purposes, or (2) anything designed or sold for incorporation + into a dwelling. In determining whether a product is a consumer product, + doubtful cases shall be resolved in favor of coverage. For a particular + product received by a particular user, "normally used" refers to a + typical or common use of that class of product, regardless of the status + of the particular user or of the way in which the particular user + actually uses, or expects or is expected to use, the product. A product + is a consumer product regardless of whether the product has substantial + commercial, industrial or non-consumer uses, unless such uses represent + the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, + procedures, authorization keys, or other information required to install + and execute modified versions of a covered work in that User Product from + a modified version of its Corresponding Source. The information must + suffice to ensure that the continued functioning of the modified object + code is in no case prevented or interfered with solely because + modification has been made. + + If you convey an object code work under this section in, or with, or + specifically for use in, a User Product, and the conveying occurs as + part of a transaction in which the right of possession and use of the + User Product is transferred to the recipient in perpetuity or for a + fixed term (regardless of how the transaction is characterized), the + Corresponding Source conveyed under this section must be accompanied + by the Installation Information. But this requirement does not apply + if neither you nor any third party retains the ability to install + modified object code on the User Product (for example, the work has + been installed in ROM). + + The requirement to provide Installation Information does not include a + requirement to continue to provide support service, warranty, or updates + for a work that has been modified or installed by the recipient, or for + the User Product in which it has been modified or installed. Access to a + network may be denied when the modification itself materially and + adversely affects the operation of the network or violates the rules and + protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, + in accord with this section must be in a format that is publicly + documented (and with an implementation available to the public in + source code form), and must require no special password or key for + unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this + License by making exceptions from one or more of its conditions. + Additional permissions that are applicable to the entire Program shall + be treated as though they were included in this License, to the extent + that they are valid under applicable law. If additional permissions + apply only to part of the Program, that part may be used separately + under those permissions, but the entire Program remains governed by + this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option + remove any additional permissions from that copy, or from any part of + it. (Additional permissions may be written to require their own + removal in certain cases when you modify the work.) You may place + additional permissions on material, added by you to a covered work, + for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you + add to a covered work, you may (if authorized by the copyright holders of + that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further + restrictions" within the meaning of section 10. If the Program as you + received it, or any part of it, contains a notice stating that it is + governed by this License along with a term that is a further + restriction, you may remove that term. If a license document contains + a further restriction but permits relicensing or conveying under this + License, you may add to a covered work material governed by the terms + of that license document, provided that the further restriction does + not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you + must place, in the relevant source files, a statement of the + additional terms that apply to those files, or a notice indicating + where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the + form of a separately written license, or stated as exceptions; + the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly + provided under this License. Any attempt otherwise to propagate or + modify it is void, and will automatically terminate your rights under + this License (including any patent licenses granted under the third + paragraph of section 11). + + However, if you cease all violation of this License, then your + license from a particular copyright holder is reinstated (a) + provisionally, unless and until the copyright holder explicitly and + finally terminates your license, and (b) permanently, if the copyright + holder fails to notify you of the violation by some reasonable means + prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is + reinstated permanently if the copyright holder notifies you of the + violation by some reasonable means, this is the first time you have + received notice of violation of this License (for any work) from that + copyright holder, and you cure the violation prior to 30 days after + your receipt of the notice. + + Termination of your rights under this section does not terminate the + licenses of parties who have received copies or rights from you under + this License. If your rights have been terminated and not permanently + reinstated, you do not qualify to receive new licenses for the same + material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or + run a copy of the Program. Ancillary propagation of a covered work + occurring solely as a consequence of using peer-to-peer transmission + to receive a copy likewise does not require acceptance. However, + nothing other than this License grants you permission to propagate or + modify any covered work. These actions infringe copyright if you do + not accept this License. Therefore, by modifying or propagating a + covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically + receives a license from the original licensors, to run, modify and + propagate that work, subject to this License. You are not responsible + for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an + organization, or substantially all assets of one, or subdividing an + organization, or merging organizations. If propagation of a covered + work results from an entity transaction, each party to that + transaction who receives a copy of the work also receives whatever + licenses to the work the party's predecessor in interest had or could + give under the previous paragraph, plus a right to possession of the + Corresponding Source of the work from the predecessor in interest, if + the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the + rights granted or affirmed under this License. For example, you may + not impose a license fee, royalty, or other charge for exercise of + rights granted under this License, and you may not initiate litigation + (including a cross-claim or counterclaim in a lawsuit) alleging that + any patent claim is infringed by making, using, selling, offering for + sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this + License of the Program or a work on which the Program is based. The + work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims + owned or controlled by the contributor, whether already acquired or + hereafter acquired, that would be infringed by some manner, permitted + by this License, of making, using, or selling its contributor version, + but do not include claims that would be infringed only as a + consequence of further modification of the contributor version. For + purposes of this definition, "control" includes the right to grant + patent sublicenses in a manner consistent with the requirements of + this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free + patent license under the contributor's essential patent claims, to + make, use, sell, offer for sale, import and otherwise run, modify and + propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express + agreement or commitment, however denominated, not to enforce a patent + (such as an express permission to practice a patent or covenant not to + sue for patent infringement). To "grant" such a patent license to a + party means to make such an agreement or commitment not to enforce a + patent against the party. + + If you convey a covered work, knowingly relying on a patent license, + and the Corresponding Source of the work is not available for anyone + to copy, free of charge and under the terms of this License, through a + publicly available network server or other readily accessible means, + then you must either (1) cause the Corresponding Source to be so + available, or (2) arrange to deprive yourself of the benefit of the + patent license for this particular work, or (3) arrange, in a manner + consistent with the requirements of this License, to extend the patent + license to downstream recipients. "Knowingly relying" means you have + actual knowledge that, but for the patent license, your conveying the + covered work in a country, or your recipient's use of the covered work + in a country, would infringe one or more identifiable patents in that + country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or + arrangement, you convey, or propagate by procuring conveyance of, a + covered work, and grant a patent license to some of the parties + receiving the covered work authorizing them to use, propagate, modify + or convey a specific copy of the covered work, then the patent license + you grant is automatically extended to all recipients of the covered + work and works based on it. + + A patent license is "discriminatory" if it does not include within + the scope of its coverage, prohibits the exercise of, or is + conditioned on the non-exercise of one or more of the rights that are + specifically granted under this License. You may not convey a covered + work if you are a party to an arrangement with a third party that is + in the business of distributing software, under which you make payment + to the third party based on the extent of your activity of conveying + the work, and under which the third party grants, to any of the + parties who would receive the covered work from you, a discriminatory + patent license (a) in connection with copies of the covered work + conveyed by you (or copies made from those copies), or (b) primarily + for and in connection with specific products or compilations that + contain the covered work, unless you entered into that arrangement, + or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting + any implied license or other defenses to infringement that may + otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or + otherwise) that contradict the conditions of this License, they do not + excuse you from the conditions of this License. If you cannot convey a + covered work so as to satisfy simultaneously your obligations under this + License and any other pertinent obligations, then as a consequence you may + not convey it at all. For example, if you agree to terms that obligate you + to collect a royalty for further conveying from those to whom you convey + the Program, the only way you could satisfy both those terms and this + License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the + Program, your modified version must prominently offer all users + interacting with it remotely through a computer network (if your version + supports such interaction) an opportunity to receive the Corresponding + Source of your version by providing access to the Corresponding Source + from a network server at no charge, through some standard or customary + means of facilitating copying of software. This Corresponding Source + shall include the Corresponding Source for any work covered by version 3 + of the GNU General Public License that is incorporated pursuant to the + following paragraph. + + Notwithstanding any other provision of this License, you have + permission to link or combine any covered work with a work licensed + under version 3 of the GNU General Public License into a single + combined work, and to convey the resulting work. The terms of this + License will continue to apply to the part which is the covered work, + but the work with which it is combined will remain governed by version + 3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of + the GNU Affero General Public License from time to time. Such new versions + will be similar in spirit to the present version, but may differ in detail to + address new problems or concerns. + + Each version is given a distinguishing version number. If the + Program specifies that a certain numbered version of the GNU Affero General + Public License "or any later version" applies to it, you have the + option of following the terms and conditions either of that numbered + version or of any later version published by the Free Software + Foundation. If the Program does not specify a version number of the + GNU Affero General Public License, you may choose any version ever published + by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future + versions of the GNU Affero General Public License can be used, that proxy's + public statement of acceptance of a version permanently authorizes you + to choose that version for the Program. + + Later license versions may give you additional or different + permissions. However, no additional obligations are imposed on any + author or copyright holder as a result of your choosing to follow a + later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY + APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT + HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY + OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, + THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM + IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF + ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING + WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS + THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY + GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE + USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF + DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD + PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), + EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF + SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided + above cannot be given local legal effect according to their terms, + reviewing courts shall apply local law that most closely approximates + an absolute waiver of all civil liability in connection with the + Program, unless a warranty or assumption of liability accompanies a + copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest + possible use to the public, the best way to achieve this is to make it + free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest + to attach them to the start of each source file to most effectively + state the exclusion of warranty; and each file should have at least + the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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 . + + Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer + network, you should also make sure that it provides a way for users to + get its source. For example, if your program is a web application, its + interface could display a "Source" link that leads users to an archive + of the code. There are many ways you could offer source, and different + solutions will be better for different programs; see section 13 for the + specific requirements. + + You should also get your employer (if you work as a programmer) or school, + if any, to sign a "copyright disclaimer" for the program, if necessary. + For more information on this, and how to apply and follow the GNU LGPL, see + . diff --git a/connector/doc/project/roadmap.rst b/connector/doc/project/roadmap.rst new file mode 100644 index 000000000..cb605f5f3 --- /dev/null +++ b/connector/doc/project/roadmap.rst @@ -0,0 +1,13 @@ +.. _roadmap: + +####### +Roadmap +####### + +Here is a list of things we may agree to merge. + +* Add facilities to parse the errors from the jobs so we can replace it + by more contextual and helpful errors. + +* A logger which keeps in a buffer all the logs and flushes them when an error + occurs in a synchronization, clears them if it succeeded diff --git a/connector/exception.py b/connector/exception.py new file mode 100644 index 000000000..0ab2acf48 --- /dev/null +++ b/connector/exception.py @@ -0,0 +1,41 @@ +# Copyright 2012 Camptocamp SA +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html) + +from odoo.addons.queue_job.exception import JobError, RetryableJobError + +# Connector related errors + + +class ConnectorException(Exception): + """Base Exception for the connectors""" + + +class NoConnectorUnitError(ConnectorException): + """No ConnectorUnit has been found""" + + +class InvalidDataError(ConnectorException): + """Data Invalid""" + + +# Job related errors + + +class MappingError(ConnectorException): + """An error occurred during a mapping transformation.""" + + +class NetworkRetryableError(RetryableJobError): + """A network error caused the failure of the job, it can be retried later.""" + + +class NoExternalId(RetryableJobError): + """No External ID found, it can be retried later.""" + + +class IDMissingInBackend(JobError): + """The ID does not exist in the backend""" + + +class ManyIDSInBackend(JobError): + """Unique key exists many times in backend""" diff --git a/connector/i18n/am.po b/connector/i18n/am.po new file mode 100644 index 000000000..b9abcd366 --- /dev/null +++ b/connector/i18n/am.po @@ -0,0 +1,95 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * connector +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-03-10 03:36+0000\n" +"PO-Revision-Date: 2017-03-10 03:36+0000\n" +"Last-Translator: OCA Transbot , 2017\n" +"Language-Team: Amharic (https://www.transifex.com/oca/teams/23907/am/)\n" +"Language: am\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#. module: connector +#: model:ir.module.category,name:connector.module_category_connector +msgid "Connector" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_connector_backend +msgid "Connector Backend" +msgstr "" + +#. module: connector +#: model:res.groups,name:connector.group_connector_manager +msgid "Connector Manager" +msgstr "" + +#. module: connector +#: model:ir.ui.menu,name:connector.menu_connector +#: model:ir.ui.menu,name:connector.menu_connector_root +#: model_terms:ir.ui.view,arch_db:connector.view_partner_connector_form +msgid "Connectors" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_external_binding +msgid "External Binding (abstract)" +msgstr "" + +#. module: connector +#: model:ir.model.fields,field_description:connector.field_external_binding__sync_date +msgid "Last synchronization date" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Nothing to export." +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_queue_job +msgid "Queue Job" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Record exported with ID %s on Backend." +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/models/queue_job.py:0 +#, python-format +msgid "Related Record" +msgstr "" + +#~ msgid "ID" +#~ msgstr "ID" + +#~ msgid "Cancel" +#~ msgstr "Cancelar" + +#~ msgid "Created by" +#~ msgstr "Creado por" + +#~ msgid "Created on" +#~ msgstr "Creado en" + +#~ msgid "Last Updated by" +#~ msgstr "Última actualización por" + +#~ msgid "Last Updated on" +#~ msgstr "Última actualización en" diff --git a/connector/i18n/ar.po b/connector/i18n/ar.po new file mode 100644 index 000000000..907bc1051 --- /dev/null +++ b/connector/i18n/ar.po @@ -0,0 +1,81 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * connector +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-03-10 03:36+0000\n" +"PO-Revision-Date: 2017-03-10 03:36+0000\n" +"Last-Translator: OCA Transbot , 2017\n" +"Language-Team: Arabic (https://www.transifex.com/oca/teams/23907/ar/)\n" +"Language: ar\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 " +"&& n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" + +#. module: connector +#: model:ir.module.category,name:connector.module_category_connector +msgid "Connector" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_connector_backend +msgid "Connector Backend" +msgstr "" + +#. module: connector +#: model:res.groups,name:connector.group_connector_manager +msgid "Connector Manager" +msgstr "" + +#. module: connector +#: model:ir.ui.menu,name:connector.menu_connector +#: model:ir.ui.menu,name:connector.menu_connector_root +#: model_terms:ir.ui.view,arch_db:connector.view_partner_connector_form +msgid "Connectors" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_external_binding +msgid "External Binding (abstract)" +msgstr "" + +#. module: connector +#: model:ir.model.fields,field_description:connector.field_external_binding__sync_date +msgid "Last synchronization date" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Nothing to export." +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_queue_job +msgid "Queue Job" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Record exported with ID %s on Backend." +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/models/queue_job.py:0 +#, python-format +msgid "Related Record" +msgstr "" + +#~ msgid "Cancel" +#~ msgstr "إلغاء" diff --git a/connector/i18n/ca.po b/connector/i18n/ca.po new file mode 100644 index 000000000..fc502e132 --- /dev/null +++ b/connector/i18n/ca.po @@ -0,0 +1,167 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * connector +# +# Translators: +# OCA Transbot , 2018 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 11.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-01-05 16:56+0000\n" +"PO-Revision-Date: 2018-01-05 16:56+0000\n" +"Last-Translator: OCA Transbot , 2018\n" +"Language-Team: Catalan (https://www.transifex.com/oca/teams/23907/ca/)\n" +"Language: ca\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: connector +#: model:ir.module.category,name:connector.module_category_connector +msgid "Connector" +msgstr "Connector" + +#. module: connector +#: model:ir.model,name:connector.model_connector_backend +msgid "Connector Backend" +msgstr "Backend del Connector" + +#. module: connector +#: model:res.groups,name:connector.group_connector_manager +msgid "Connector Manager" +msgstr "Administrador del connector" + +#. module: connector +#: model:ir.ui.menu,name:connector.menu_connector +#: model:ir.ui.menu,name:connector.menu_connector_root +#: model_terms:ir.ui.view,arch_db:connector.view_partner_connector_form +msgid "Connectors" +msgstr "Connectors" + +#. module: connector +#: model:ir.model,name:connector.model_external_binding +msgid "External Binding (abstract)" +msgstr "Lligam extern (abstracte)" + +#. module: connector +#: model:ir.model.fields,field_description:connector.field_external_binding__sync_date +msgid "Last synchronization date" +msgstr "Darrera data de sincronització" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Nothing to export." +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_queue_job +msgid "Queue Job" +msgstr "Tasca de Cua" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Record exported with ID %s on Backend." +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/models/queue_job.py:0 +#, python-format +msgid "Related Record" +msgstr "Registre relacionat" + +#~ msgid "ID" +#~ msgstr "ID" + +#~ msgid "A %s needs a review." +#~ msgstr "Un %s necessita revisió." + +#~ msgid "Cancel" +#~ msgstr "Cancel·la" + +#~ msgid "Checkpoint" +#~ msgstr "Punt de control" + +#~ msgid "Checkpoints" +#~ msgstr "Punts de control" + +#~ msgid "Checkpoints Review" +#~ msgstr "Revisió de punts de control" + +#~ msgid "Click on the" +#~ msgstr "Fes clic en el" + +#~ msgid "Connector Checkpoint" +#~ msgstr "Punts de control del connector" + +#~ msgid "Created by" +#~ msgstr "Creat per" + +#~ msgid "Created on" +#~ msgstr "Creat a" + +#~ msgid "Group By..." +#~ msgstr "Agrupa per..." + +#~ msgid "Imported from" +#~ msgstr "Importat de" + +#~ msgid "Last Updated by" +#~ msgstr "Darrear modificació per" + +#~ msgid "Last Updated on" +#~ msgstr "Darrera modificació el" + +#~ msgid "Model" +#~ msgstr "Model" + +#~ msgid "Need Review" +#~ msgstr "Necessita Revisió" + +#~ msgid "Record ID" +#~ msgstr "ID Registre" + +#~ msgid "Review Checkpoints" +#~ msgstr "Revisa Punts-Control" + +#~ msgid "Reviewed" +#~ msgstr "Revisat" + +#~ msgid "Set as reviewed" +#~ msgstr "Marcat com revisat" + +#~ msgid "Status" +#~ msgstr "Estat" + +#~ msgid "The record has been imported from this backend" +#~ msgstr "El registre ha estat importat des d'aquest backend" + +#~ msgid "The selected checkpoints will be set as reviewed." +#~ msgstr "Els seleccionats seran marcats com revisats. " + +#~ msgid "to verify it:" +#~ msgstr "per verificar:" + +#~ msgid "Apply" +#~ msgstr "Aplica" + +#~ msgid "Backends" +#~ msgstr "Backends" + +#~ msgid "Configure Connector" +#~ msgstr "Configura el connector" + +#~ msgid "Connector Configuration" +#~ msgstr "Configuració del connector" + +#~ msgid "Open Connector Menu" +#~ msgstr "Menú de Open Connector" + +#~ msgid "or" +#~ msgstr "o " diff --git a/connector/i18n/connector.pot b/connector/i18n/connector.pot new file mode 100644 index 000000000..b22e38979 --- /dev/null +++ b/connector/i18n/connector.pot @@ -0,0 +1,73 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * connector +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: connector +#: model:ir.module.category,name:connector.module_category_connector +msgid "Connector" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_connector_backend +msgid "Connector Backend" +msgstr "" + +#. module: connector +#: model:res.groups,name:connector.group_connector_manager +msgid "Connector Manager" +msgstr "" + +#. module: connector +#: model:ir.ui.menu,name:connector.menu_connector +#: model:ir.ui.menu,name:connector.menu_connector_root +#: model_terms:ir.ui.view,arch_db:connector.view_partner_connector_form +msgid "Connectors" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_external_binding +msgid "External Binding (abstract)" +msgstr "" + +#. module: connector +#: model:ir.model.fields,field_description:connector.field_external_binding__sync_date +msgid "Last synchronization date" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Nothing to export." +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_queue_job +msgid "Queue Job" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Record exported with ID %s on Backend." +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/models/queue_job.py:0 +#, python-format +msgid "Related Record" +msgstr "" diff --git a/connector/i18n/cs.po b/connector/i18n/cs.po new file mode 100644 index 000000000..c3fa486aa --- /dev/null +++ b/connector/i18n/cs.po @@ -0,0 +1,80 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * connector +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-03-10 03:36+0000\n" +"PO-Revision-Date: 2017-03-10 03:36+0000\n" +"Last-Translator: OCA Transbot , 2017\n" +"Language-Team: Czech (https://www.transifex.com/oca/teams/23907/cs/)\n" +"Language: cs\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" + +#. module: connector +#: model:ir.module.category,name:connector.module_category_connector +msgid "Connector" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_connector_backend +msgid "Connector Backend" +msgstr "" + +#. module: connector +#: model:res.groups,name:connector.group_connector_manager +msgid "Connector Manager" +msgstr "" + +#. module: connector +#: model:ir.ui.menu,name:connector.menu_connector +#: model:ir.ui.menu,name:connector.menu_connector_root +#: model_terms:ir.ui.view,arch_db:connector.view_partner_connector_form +msgid "Connectors" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_external_binding +msgid "External Binding (abstract)" +msgstr "" + +#. module: connector +#: model:ir.model.fields,field_description:connector.field_external_binding__sync_date +msgid "Last synchronization date" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Nothing to export." +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_queue_job +msgid "Queue Job" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Record exported with ID %s on Backend." +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/models/queue_job.py:0 +#, python-format +msgid "Related Record" +msgstr "" + +#~ msgid "Cancel" +#~ msgstr "Zrušit" diff --git a/connector/i18n/de.po b/connector/i18n/de.po new file mode 100644 index 000000000..4a3e3d7c9 --- /dev/null +++ b/connector/i18n/de.po @@ -0,0 +1,188 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * connector +# +# Translators: +# OCA Transbot , 2018 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 11.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-01-05 16:56+0000\n" +"PO-Revision-Date: 2018-01-05 16:56+0000\n" +"Last-Translator: OCA Transbot , 2018\n" +"Language-Team: German (https://www.transifex.com/oca/teams/23907/de/)\n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: connector +#: model:ir.module.category,name:connector.module_category_connector +msgid "Connector" +msgstr "Connector" + +#. module: connector +#: model:ir.model,name:connector.model_connector_backend +msgid "Connector Backend" +msgstr "Connector Backend" + +#. module: connector +#: model:res.groups,name:connector.group_connector_manager +msgid "Connector Manager" +msgstr "Connector Manager" + +#. module: connector +#: model:ir.ui.menu,name:connector.menu_connector +#: model:ir.ui.menu,name:connector.menu_connector_root +#: model_terms:ir.ui.view,arch_db:connector.view_partner_connector_form +msgid "Connectors" +msgstr "Connector" + +#. module: connector +#: model:ir.model,name:connector.model_external_binding +msgid "External Binding (abstract)" +msgstr "Externe Verbindung (abstrakt)" + +#. module: connector +#: model:ir.model.fields,field_description:connector.field_external_binding__sync_date +msgid "Last synchronization date" +msgstr "Letztes Synchronisationsdatum" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Nothing to export." +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_queue_job +msgid "Queue Job" +msgstr "Aufgabe in Warteschlange einreihen" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Record exported with ID %s on Backend." +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/models/queue_job.py:0 +#, python-format +msgid "Related Record" +msgstr "Zugehöriger Datensatz" + +#~ msgid "Display Name" +#~ msgstr "Anzeigebezeichnung" + +#~ msgid "ID" +#~ msgstr "ID" + +#~ msgid "Last Modified on" +#~ msgstr "Zuletzt aktualisiert am" + +#~ msgid "A %s needs a review." +#~ msgstr "Ein %s erfordert Sichtung" + +#~ msgid "Cancel" +#~ msgstr "Abbrechen" + +#~ msgid "Checkpoint" +#~ msgstr "Checkpunkt" + +#~ msgid "Checkpoints" +#~ msgstr "Checkpunkte" + +#~ msgid "Checkpoints Review" +#~ msgstr "Checkpunkt Überprüfung" + +#~ msgid "Click on the" +#~ msgstr "Klicken Sie auf den" + +#~ msgid "Connector Checkpoint" +#~ msgstr "Connector Checkpunkt" + +#~ msgid "Created by" +#~ msgstr "Angelegt durch" + +#~ msgid "Created on" +#~ msgstr "Angelegt am" + +#~ msgid "Group By..." +#~ msgstr "Gruppieren nach ..." + +#~ msgid "Imported from" +#~ msgstr "Importiert von" + +#~ msgid "Last Updated by" +#~ msgstr "Zuletzt aktualisiert durch" + +#~ msgid "Last Updated on" +#~ msgstr "Zuletzt aktualisiert am" + +#~ msgid "Model" +#~ msgstr "Modell" + +#~ msgid "Name of the record to review" +#~ msgstr "Bezeichnung des zu prüfenden Datensatzes" + +#~ msgid "Need Review" +#~ msgstr "Benötigt Prüfung" + +#~ msgid "No record to check." +#~ msgstr "Kein Datensatz zu prüfen." + +#~ msgid "Record" +#~ msgstr "Datensatz" + +#~ msgid "Record ID" +#~ msgstr "Datensatz Nr." + +#~ msgid "Record Name" +#~ msgstr "Datensatz-Bezeichnung" + +#~ msgid "Review Checkpoints" +#~ msgstr "Überprüfungs Checkpunkte" + +#~ msgid "Reviewed" +#~ msgstr "Überprüft" + +#~ msgid "Set as reviewed" +#~ msgstr "Als Überprüft markieren" + +#~ msgid "Status" +#~ msgstr "Status" + +#~ msgid "The record has been imported from this backend" +#~ msgstr "Der Eintrag wurde von diesem Backend importiert." + +#~ msgid "The record to review." +#~ msgstr "Der zu prüfende Datensatz." + +#~ msgid "The selected checkpoints will be set as reviewed." +#~ msgstr "Die ausgewählten Checkpunkte werden als überprüft markiert." + +#~ msgid "to verify it:" +#~ msgstr "es zu überprüfen:" + +#~ msgid "Apply" +#~ msgstr "anwenden" + +#~ msgid "Backends" +#~ msgstr "Backends" + +#~ msgid "Configure Connector" +#~ msgstr "Connector konfigurieren" + +#~ msgid "Connector Configuration" +#~ msgstr "Connector-Einstellungen" + +#~ msgid "Open Connector Menu" +#~ msgstr "Open Connector Menü" + +#~ msgid "or" +#~ msgstr "oder" diff --git a/connector/i18n/el_GR.po b/connector/i18n/el_GR.po new file mode 100644 index 000000000..73f0f26d9 --- /dev/null +++ b/connector/i18n/el_GR.po @@ -0,0 +1,93 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * connector +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-03-10 03:36+0000\n" +"PO-Revision-Date: 2017-03-10 03:36+0000\n" +"Last-Translator: OCA Transbot , 2017\n" +"Language-Team: Greek (Greece) (https://www.transifex.com/oca/teams/23907/" +"el_GR/)\n" +"Language: el_GR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: connector +#: model:ir.module.category,name:connector.module_category_connector +msgid "Connector" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_connector_backend +msgid "Connector Backend" +msgstr "" + +#. module: connector +#: model:res.groups,name:connector.group_connector_manager +msgid "Connector Manager" +msgstr "" + +#. module: connector +#: model:ir.ui.menu,name:connector.menu_connector +#: model:ir.ui.menu,name:connector.menu_connector_root +#: model_terms:ir.ui.view,arch_db:connector.view_partner_connector_form +msgid "Connectors" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_external_binding +msgid "External Binding (abstract)" +msgstr "" + +#. module: connector +#: model:ir.model.fields,field_description:connector.field_external_binding__sync_date +msgid "Last synchronization date" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Nothing to export." +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_queue_job +msgid "Queue Job" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Record exported with ID %s on Backend." +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/models/queue_job.py:0 +#, python-format +msgid "Related Record" +msgstr "" + +#~ msgid "ID" +#~ msgstr "Κωδικός" + +#~ msgid "Created by" +#~ msgstr "Δημιουργήθηκε από " + +#~ msgid "Created on" +#~ msgstr "Δημιουργήθηκε στις" + +#~ msgid "Last Updated by" +#~ msgstr "Τελευταία ενημέρωση από" + +#~ msgid "Last Updated on" +#~ msgstr "Τελευταία ενημέρωση στις" diff --git a/connector/i18n/es.po b/connector/i18n/es.po new file mode 100644 index 000000000..827e370d8 --- /dev/null +++ b/connector/i18n/es.po @@ -0,0 +1,168 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * connector +# +# Translators: +# OCA Transbot , 2018 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 11.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-01-05 16:56+0000\n" +"PO-Revision-Date: 2023-08-02 13:09+0000\n" +"Last-Translator: Ivorra78 \n" +"Language-Team: Spanish (https://www.transifex.com/oca/teams/23907/es/)\n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.17\n" + +#. module: connector +#: model:ir.module.category,name:connector.module_category_connector +msgid "Connector" +msgstr "Conector" + +#. module: connector +#: model:ir.model,name:connector.model_connector_backend +msgid "Connector Backend" +msgstr "Conector de servidor" + +#. module: connector +#: model:res.groups,name:connector.group_connector_manager +msgid "Connector Manager" +msgstr "Administrador del Conector" + +#. module: connector +#: model:ir.ui.menu,name:connector.menu_connector +#: model:ir.ui.menu,name:connector.menu_connector_root +#: model_terms:ir.ui.view,arch_db:connector.view_partner_connector_form +msgid "Connectors" +msgstr "Conectores" + +#. module: connector +#: model:ir.model,name:connector.model_external_binding +msgid "External Binding (abstract)" +msgstr "Unión Externa (abstracto)" + +#. module: connector +#: model:ir.model.fields,field_description:connector.field_external_binding__sync_date +msgid "Last synchronization date" +msgstr "Última fecha de sincronización" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Nothing to export." +msgstr "Nada que exportar." + +#. module: connector +#: model:ir.model,name:connector.model_queue_job +msgid "Queue Job" +msgstr "Trabajo de Cola" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Record exported with ID %s on Backend." +msgstr "Registro exportado con ID %s en el servidor." + +#. module: connector +#. odoo-python +#: code:addons/connector/models/queue_job.py:0 +#, python-format +msgid "Related Record" +msgstr "Registro relacionado" + +#~ msgid "Display Name" +#~ msgstr "Nombre mostrado" + +#~ msgid "ID" +#~ msgstr "ID" + +#~ msgid "Last Modified on" +#~ msgstr "Última modificación el" + +#~ msgid "Cancel" +#~ msgstr "Cancelar" + +#~ msgid "Checkpoint" +#~ msgstr "Punto Control" + +#~ msgid "Checkpoints" +#~ msgstr "Puntos de control" + +#~ msgid "Checkpoints Review" +#~ msgstr "Revisión de puntos de control" + +#~ msgid "Click on the" +#~ msgstr "Hcer clic en" + +#~ msgid "Connector Checkpoint" +#~ msgstr "Punto de Control del Conector" + +#~ msgid "Created by" +#~ msgstr "Creado por" + +#~ msgid "Created on" +#~ msgstr "Creado en" + +#~ msgid "Group By..." +#~ msgstr "Agrupar Por..." + +#~ msgid "Imported from" +#~ msgstr "Importado de" + +#~ msgid "Last Updated by" +#~ msgstr "Última actualización por" + +#~ msgid "Last Updated on" +#~ msgstr "Última actualización el" + +#~ msgid "Model" +#~ msgstr "Modelo" + +#~ msgid "Need Review" +#~ msgstr "Necesita Revisión" + +#~ msgid "Record ID" +#~ msgstr "ID de Registro" + +#~ msgid "Review Checkpoints" +#~ msgstr "Puntos de Control de Revisión" + +#~ msgid "Reviewed" +#~ msgstr "Revisado" + +#~ msgid "Set as reviewed" +#~ msgstr "Marcar como Revisado" + +#~ msgid "Status" +#~ msgstr "Estado" + +#~ msgid "The record has been imported from this backend" +#~ msgstr "El registro ha sido importado de esta área de administación" + +#~ msgid "The selected checkpoints will be set as reviewed." +#~ msgstr "Los puntos de control seleccionados serán marcados como revisados" + +#~ msgid "to verify it:" +#~ msgstr "para verificar:" + +#~ msgid "Apply" +#~ msgstr "Aplicar" + +#~ msgid "Backends" +#~ msgstr "Áreas de administración" + +#~ msgid "Configure Connector" +#~ msgstr "Configurar el conector" + +#~ msgid "Open Connector Menu" +#~ msgstr "Menú del Open Connector" + +#~ msgid "or" +#~ msgstr "o" diff --git a/connector/i18n/es_CR.po b/connector/i18n/es_CR.po new file mode 100644 index 000000000..7a1c507b9 --- /dev/null +++ b/connector/i18n/es_CR.po @@ -0,0 +1,81 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * connector +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-03-10 03:36+0000\n" +"PO-Revision-Date: 2017-03-10 03:36+0000\n" +"Last-Translator: OCA Transbot , 2017\n" +"Language-Team: Spanish (Costa Rica) (https://www.transifex.com/oca/" +"teams/23907/es_CR/)\n" +"Language: es_CR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: connector +#: model:ir.module.category,name:connector.module_category_connector +msgid "Connector" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_connector_backend +msgid "Connector Backend" +msgstr "" + +#. module: connector +#: model:res.groups,name:connector.group_connector_manager +msgid "Connector Manager" +msgstr "" + +#. module: connector +#: model:ir.ui.menu,name:connector.menu_connector +#: model:ir.ui.menu,name:connector.menu_connector_root +#: model_terms:ir.ui.view,arch_db:connector.view_partner_connector_form +msgid "Connectors" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_external_binding +msgid "External Binding (abstract)" +msgstr "" + +#. module: connector +#: model:ir.model.fields,field_description:connector.field_external_binding__sync_date +msgid "Last synchronization date" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Nothing to export." +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_queue_job +msgid "Queue Job" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Record exported with ID %s on Backend." +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/models/queue_job.py:0 +#, python-format +msgid "Related Record" +msgstr "" + +#~ msgid "Cancel" +#~ msgstr "Cancelar" diff --git a/connector/i18n/es_EC.po b/connector/i18n/es_EC.po new file mode 100644 index 000000000..f37b41ab6 --- /dev/null +++ b/connector/i18n/es_EC.po @@ -0,0 +1,81 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * connector +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-03-10 03:36+0000\n" +"PO-Revision-Date: 2017-03-10 03:36+0000\n" +"Last-Translator: OCA Transbot , 2017\n" +"Language-Team: Spanish (Ecuador) (https://www.transifex.com/oca/teams/23907/" +"es_EC/)\n" +"Language: es_EC\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: connector +#: model:ir.module.category,name:connector.module_category_connector +msgid "Connector" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_connector_backend +msgid "Connector Backend" +msgstr "" + +#. module: connector +#: model:res.groups,name:connector.group_connector_manager +msgid "Connector Manager" +msgstr "" + +#. module: connector +#: model:ir.ui.menu,name:connector.menu_connector +#: model:ir.ui.menu,name:connector.menu_connector_root +#: model_terms:ir.ui.view,arch_db:connector.view_partner_connector_form +msgid "Connectors" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_external_binding +msgid "External Binding (abstract)" +msgstr "" + +#. module: connector +#: model:ir.model.fields,field_description:connector.field_external_binding__sync_date +msgid "Last synchronization date" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Nothing to export." +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_queue_job +msgid "Queue Job" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Record exported with ID %s on Backend." +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/models/queue_job.py:0 +#, python-format +msgid "Related Record" +msgstr "" + +#~ msgid "Cancel" +#~ msgstr "Cancelar" diff --git a/connector/i18n/es_ES.po b/connector/i18n/es_ES.po new file mode 100644 index 000000000..1992c82ef --- /dev/null +++ b/connector/i18n/es_ES.po @@ -0,0 +1,96 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * connector +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-03-10 03:36+0000\n" +"PO-Revision-Date: 2017-03-10 03:36+0000\n" +"Last-Translator: OCA Transbot , 2017\n" +"Language-Team: Spanish (Spain) (https://www.transifex.com/oca/teams/23907/" +"es_ES/)\n" +"Language: es_ES\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: connector +#: model:ir.module.category,name:connector.module_category_connector +msgid "Connector" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_connector_backend +msgid "Connector Backend" +msgstr "" + +#. module: connector +#: model:res.groups,name:connector.group_connector_manager +msgid "Connector Manager" +msgstr "" + +#. module: connector +#: model:ir.ui.menu,name:connector.menu_connector +#: model:ir.ui.menu,name:connector.menu_connector_root +#: model_terms:ir.ui.view,arch_db:connector.view_partner_connector_form +msgid "Connectors" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_external_binding +msgid "External Binding (abstract)" +msgstr "" + +#. module: connector +#: model:ir.model.fields,field_description:connector.field_external_binding__sync_date +msgid "Last synchronization date" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Nothing to export." +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_queue_job +msgid "Queue Job" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Record exported with ID %s on Backend." +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/models/queue_job.py:0 +#, python-format +msgid "Related Record" +msgstr "" + +#~ msgid "ID" +#~ msgstr "ID" + +#~ msgid "Cancel" +#~ msgstr "Cancelar" + +#~ msgid "Created by" +#~ msgstr "Creado por" + +#~ msgid "Created on" +#~ msgstr "Creado en" + +#~ msgid "Last Updated by" +#~ msgstr "Última actualización por" + +#~ msgid "Last Updated on" +#~ msgstr "Última actualización en" diff --git a/connector/i18n/es_MX.po b/connector/i18n/es_MX.po new file mode 100644 index 000000000..86d027ae5 --- /dev/null +++ b/connector/i18n/es_MX.po @@ -0,0 +1,102 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * connector +# +# Translators: +# OCA Transbot , 2018 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 11.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-01-05 16:56+0000\n" +"PO-Revision-Date: 2018-01-05 16:56+0000\n" +"Last-Translator: OCA Transbot , 2018\n" +"Language-Team: Spanish (Mexico) (https://www.transifex.com/oca/teams/23907/" +"es_MX/)\n" +"Language: es_MX\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: connector +#: model:ir.module.category,name:connector.module_category_connector +msgid "Connector" +msgstr "Conector" + +#. module: connector +#: model:ir.model,name:connector.model_connector_backend +msgid "Connector Backend" +msgstr "" + +#. module: connector +#: model:res.groups,name:connector.group_connector_manager +msgid "Connector Manager" +msgstr "" + +#. module: connector +#: model:ir.ui.menu,name:connector.menu_connector +#: model:ir.ui.menu,name:connector.menu_connector_root +#: model_terms:ir.ui.view,arch_db:connector.view_partner_connector_form +msgid "Connectors" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_external_binding +msgid "External Binding (abstract)" +msgstr "" + +#. module: connector +#: model:ir.model.fields,field_description:connector.field_external_binding__sync_date +msgid "Last synchronization date" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Nothing to export." +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_queue_job +msgid "Queue Job" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Record exported with ID %s on Backend." +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/models/queue_job.py:0 +#, python-format +msgid "Related Record" +msgstr "" + +#~ msgid "A %s needs a review." +#~ msgstr "El %s necesita revisión." + +#~ msgid "Cancel" +#~ msgstr "Cancelar" + +#~ msgid "Imported from" +#~ msgstr "Importado de" + +#~ msgid "Model" +#~ msgstr "Modelo" + +#~ msgid "Need Review" +#~ msgstr "Necesita Revisión" + +#~ msgid "Reviewed" +#~ msgstr "Revisiado" + +#~ msgid "Apply" +#~ msgstr "Aplicar" + +#~ msgid "Configure Connector" +#~ msgstr "Configurar Conector" diff --git a/connector/i18n/es_VE.po b/connector/i18n/es_VE.po new file mode 100644 index 000000000..73d821a05 --- /dev/null +++ b/connector/i18n/es_VE.po @@ -0,0 +1,81 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * connector +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-03-10 03:36+0000\n" +"PO-Revision-Date: 2017-03-10 03:36+0000\n" +"Last-Translator: OCA Transbot , 2017\n" +"Language-Team: Spanish (Venezuela) (https://www.transifex.com/oca/" +"teams/23907/es_VE/)\n" +"Language: es_VE\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: connector +#: model:ir.module.category,name:connector.module_category_connector +msgid "Connector" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_connector_backend +msgid "Connector Backend" +msgstr "" + +#. module: connector +#: model:res.groups,name:connector.group_connector_manager +msgid "Connector Manager" +msgstr "" + +#. module: connector +#: model:ir.ui.menu,name:connector.menu_connector +#: model:ir.ui.menu,name:connector.menu_connector_root +#: model_terms:ir.ui.view,arch_db:connector.view_partner_connector_form +msgid "Connectors" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_external_binding +msgid "External Binding (abstract)" +msgstr "" + +#. module: connector +#: model:ir.model.fields,field_description:connector.field_external_binding__sync_date +msgid "Last synchronization date" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Nothing to export." +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_queue_job +msgid "Queue Job" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Record exported with ID %s on Backend." +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/models/queue_job.py:0 +#, python-format +msgid "Related Record" +msgstr "" + +#~ msgid "Cancel" +#~ msgstr "Cancelar" diff --git a/connector/i18n/et.po b/connector/i18n/et.po new file mode 100644 index 000000000..a0a22f921 --- /dev/null +++ b/connector/i18n/et.po @@ -0,0 +1,80 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * connector +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-03-10 03:36+0000\n" +"PO-Revision-Date: 2017-03-10 03:36+0000\n" +"Last-Translator: OCA Transbot , 2017\n" +"Language-Team: Estonian (https://www.transifex.com/oca/teams/23907/et/)\n" +"Language: et\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: connector +#: model:ir.module.category,name:connector.module_category_connector +msgid "Connector" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_connector_backend +msgid "Connector Backend" +msgstr "" + +#. module: connector +#: model:res.groups,name:connector.group_connector_manager +msgid "Connector Manager" +msgstr "" + +#. module: connector +#: model:ir.ui.menu,name:connector.menu_connector +#: model:ir.ui.menu,name:connector.menu_connector_root +#: model_terms:ir.ui.view,arch_db:connector.view_partner_connector_form +msgid "Connectors" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_external_binding +msgid "External Binding (abstract)" +msgstr "" + +#. module: connector +#: model:ir.model.fields,field_description:connector.field_external_binding__sync_date +msgid "Last synchronization date" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Nothing to export." +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_queue_job +msgid "Queue Job" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Record exported with ID %s on Backend." +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/models/queue_job.py:0 +#, python-format +msgid "Related Record" +msgstr "" + +#~ msgid "Cancel" +#~ msgstr "Loobu" diff --git a/connector/i18n/fi.po b/connector/i18n/fi.po new file mode 100644 index 000000000..a4bb1a76c --- /dev/null +++ b/connector/i18n/fi.po @@ -0,0 +1,98 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * connector +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-03-10 03:36+0000\n" +"PO-Revision-Date: 2017-03-10 03:36+0000\n" +"Last-Translator: OCA Transbot , 2017\n" +"Language-Team: Finnish (https://www.transifex.com/oca/teams/23907/fi/)\n" +"Language: fi\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: connector +#: model:ir.module.category,name:connector.module_category_connector +msgid "Connector" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_connector_backend +msgid "Connector Backend" +msgstr "" + +#. module: connector +#: model:res.groups,name:connector.group_connector_manager +msgid "Connector Manager" +msgstr "" + +#. module: connector +#: model:ir.ui.menu,name:connector.menu_connector +#: model:ir.ui.menu,name:connector.menu_connector_root +#: model_terms:ir.ui.view,arch_db:connector.view_partner_connector_form +msgid "Connectors" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_external_binding +msgid "External Binding (abstract)" +msgstr "" + +#. module: connector +#: model:ir.model.fields,field_description:connector.field_external_binding__sync_date +msgid "Last synchronization date" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Nothing to export." +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_queue_job +msgid "Queue Job" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Record exported with ID %s on Backend." +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/models/queue_job.py:0 +#, python-format +msgid "Related Record" +msgstr "" + +#~ msgid "Display Name" +#~ msgstr "Nimi" + +#~ msgid "ID" +#~ msgstr "ID" + +#~ msgid "Last Modified on" +#~ msgstr "Viimeksi muokattu" + +#~ msgid "Created by" +#~ msgstr "Luonut" + +#~ msgid "Created on" +#~ msgstr "Luotu" + +#~ msgid "Last Updated by" +#~ msgstr "Viimeksi päivittänyt" + +#~ msgid "Last Updated on" +#~ msgstr "Viimeksi päivitetty" diff --git a/connector/i18n/fr.po b/connector/i18n/fr.po new file mode 100644 index 000000000..1785ec20e --- /dev/null +++ b/connector/i18n/fr.po @@ -0,0 +1,211 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * connector +# +# Translators: +# OCA Transbot , 2018 +# Nicolas JEUDY , 2018 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 11.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: \n" +"PO-Revision-Date: 2021-03-26 12:11+0100\n" +"Last-Translator: Guewen Baconnier \n" +"Language-Team: French (https://www.transifex.com/oca/teams/23907/fr/)\n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Poedit 2.4.1\n" + +#. module: connector +#: model:ir.module.category,name:connector.module_category_connector +msgid "Connector" +msgstr "Connecteur" + +#. module: connector +#: model:ir.model,name:connector.model_connector_backend +msgid "Connector Backend" +msgstr "Backend de connecteur" + +#. module: connector +#: model:res.groups,name:connector.group_connector_manager +msgid "Connector Manager" +msgstr "Responsable connecteurs" + +#. module: connector +#: model:ir.ui.menu,name:connector.menu_connector +#: model:ir.ui.menu,name:connector.menu_connector_root +#: model_terms:ir.ui.view,arch_db:connector.view_partner_connector_form +msgid "Connectors" +msgstr "Connecteurs" + +#. module: connector +#: model:ir.model,name:connector.model_external_binding +msgid "External Binding (abstract)" +msgstr "Lien Externe (abstrait)" + +#. module: connector +#: model:ir.model.fields,field_description:connector.field_external_binding__sync_date +msgid "Last synchronization date" +msgstr "Dernière date de synchronisation" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Nothing to export." +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_queue_job +msgid "Queue Job" +msgstr "Queue de jobs" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Record exported with ID %s on Backend." +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/models/queue_job.py:0 +#, python-format +msgid "Related Record" +msgstr "Enregistrement lié" + +#~ msgid "Display Name" +#~ msgstr "Nom affiché" + +#~ msgid "ID" +#~ msgstr "ID" + +#~ msgid "Last Modified on" +#~ msgstr "Dernière modification le" + +#~ msgid "A %s needs a review." +#~ msgstr "Un %s a besoin d'un contrôle." + +#~ msgid "Cancel" +#~ msgstr "Annuler" + +#~ msgid "Checkpoint" +#~ msgstr "Points de contrôle" + +#~ msgid "Checkpoints" +#~ msgstr "Points de contrôle" + +#~ msgid "Checkpoints Review" +#~ msgstr "Points de contrôle" + +#~ msgid "Click on the" +#~ msgstr "Cliquer sur le" + +#~ msgid "Connector Checkpoint" +#~ msgstr "Point de contrôle" + +#~ msgid "Created by" +#~ msgstr "Créé par" + +#~ msgid "Created on" +#~ msgstr "Créé le" + +#~ msgid "Group By..." +#~ msgstr "Grouper par..." + +#~ msgid "Imported from" +#~ msgstr "Importé depuis" + +#~ msgid "Last Updated by" +#~ msgstr "Dernière mise à jour par" + +#~ msgid "Last Updated on" +#~ msgstr "Dernière mise à jour le" + +#~ msgid "Model" +#~ msgstr "Modèle" + +#~ msgid "Name of the record to review" +#~ msgstr "Nom de l'enregistrement à contrôler" + +#~ msgid "Need Review" +#~ msgstr "Nécessite un contrôle" + +#~ msgid "No record to check." +#~ msgstr "Pas d'enregistrement à contrôler." + +#~ msgid "Record" +#~ msgstr "Enregistrement" + +#~ msgid "Record ID" +#~ msgstr "ID de ressource" + +#~ msgid "Record Name" +#~ msgstr "Nom d'enregistrement" + +#~ msgid "Review Checkpoints" +#~ msgstr "Contrôler" + +#~ msgid "Reviewed" +#~ msgstr "Contrôlé" + +#~ msgid "Set as reviewed" +#~ msgstr "Passer en contrôlé" + +#~ msgid "Status" +#~ msgstr "État" + +#~ msgid "" +#~ "The connectors list the new records to verify\n" +#~ " based on their type. Only some need a manual\n" +#~ " review." +#~ msgstr "" +#~ "Les connecteurs listent les nouveaux enregistrements pour vérifier\n" +#~ " leur type. Seulement certaines nécessitent un contrôle\n" +#~ " manuel." + +#~ msgid "The record has been imported from this backend" +#~ msgstr "La ressource a été importée depuis ce backend" + +#~ msgid "The record to review." +#~ msgstr "L'enregistrement à contrôler." + +#~ msgid "The selected checkpoints will be set as reviewed." +#~ msgstr "" +#~ "Les points de contrôle sélectionnés vont être considérés comme contrôlés." + +#~ msgid "" +#~ "When a connector imports new records which have\n" +#~ " configuration or reviews to do manually, they\n" +#~ " will appear in this list. Once a record has been\n" +#~ " checked, click on the 'Reviewed' button." +#~ msgstr "" +#~ "Lorsqu'un connecteur importe de nouveaux enregistrements qui doivent être " +#~ "configurés ou révisés manuellement, ils apparaissent dans cette liste. " +#~ "Une fois qu'un enregistrement a été vérifié, cliquez sur le bouton " +#~ "\"Controlé\"." + +#~ msgid "to verify it:" +#~ msgstr "pour le vérifier :" + +#~ msgid "Apply" +#~ msgstr "Appliquer" + +#~ msgid "Backends" +#~ msgstr "Backends" + +#~ msgid "Configure Connector" +#~ msgstr "Configurer les connecteurs" + +#~ msgid "Connector Configuration" +#~ msgstr "Configuration du connecteur" + +#~ msgid "Open Connector Menu" +#~ msgstr "Ouvrir le menu du connecteur" + +#~ msgid "or" +#~ msgstr "ou" diff --git a/connector/i18n/gl.po b/connector/i18n/gl.po new file mode 100644 index 000000000..e2af73910 --- /dev/null +++ b/connector/i18n/gl.po @@ -0,0 +1,95 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * connector +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-03-10 03:36+0000\n" +"PO-Revision-Date: 2017-03-10 03:36+0000\n" +"Last-Translator: OCA Transbot , 2017\n" +"Language-Team: Galician (https://www.transifex.com/oca/teams/23907/gl/)\n" +"Language: gl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: connector +#: model:ir.module.category,name:connector.module_category_connector +msgid "Connector" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_connector_backend +msgid "Connector Backend" +msgstr "" + +#. module: connector +#: model:res.groups,name:connector.group_connector_manager +msgid "Connector Manager" +msgstr "" + +#. module: connector +#: model:ir.ui.menu,name:connector.menu_connector +#: model:ir.ui.menu,name:connector.menu_connector_root +#: model_terms:ir.ui.view,arch_db:connector.view_partner_connector_form +msgid "Connectors" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_external_binding +msgid "External Binding (abstract)" +msgstr "" + +#. module: connector +#: model:ir.model.fields,field_description:connector.field_external_binding__sync_date +msgid "Last synchronization date" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Nothing to export." +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_queue_job +msgid "Queue Job" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Record exported with ID %s on Backend." +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/models/queue_job.py:0 +#, python-format +msgid "Related Record" +msgstr "" + +#~ msgid "ID" +#~ msgstr "ID" + +#~ msgid "Cancel" +#~ msgstr "Cancelar" + +#~ msgid "Created by" +#~ msgstr "Creado por" + +#~ msgid "Created on" +#~ msgstr "Creado en" + +#~ msgid "Last Updated by" +#~ msgstr "ültima actualización por" + +#~ msgid "Last Updated on" +#~ msgstr "Última actualización en" diff --git a/connector/i18n/hr.po b/connector/i18n/hr.po new file mode 100644 index 000000000..2cfba782d --- /dev/null +++ b/connector/i18n/hr.po @@ -0,0 +1,84 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * connector +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-03-10 03:36+0000\n" +"PO-Revision-Date: 2017-03-10 03:36+0000\n" +"Last-Translator: OCA Transbot , 2017\n" +"Language-Team: Croatian (https://www.transifex.com/oca/teams/23907/hr/)\n" +"Language: hr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" + +#. module: connector +#: model:ir.module.category,name:connector.module_category_connector +msgid "Connector" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_connector_backend +msgid "Connector Backend" +msgstr "" + +#. module: connector +#: model:res.groups,name:connector.group_connector_manager +msgid "Connector Manager" +msgstr "" + +#. module: connector +#: model:ir.ui.menu,name:connector.menu_connector +#: model:ir.ui.menu,name:connector.menu_connector_root +#: model_terms:ir.ui.view,arch_db:connector.view_partner_connector_form +msgid "Connectors" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_external_binding +msgid "External Binding (abstract)" +msgstr "" + +#. module: connector +#: model:ir.model.fields,field_description:connector.field_external_binding__sync_date +msgid "Last synchronization date" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Nothing to export." +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_queue_job +msgid "Queue Job" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Record exported with ID %s on Backend." +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/models/queue_job.py:0 +#, python-format +msgid "Related Record" +msgstr "" + +#~ msgid "Group By..." +#~ msgstr "Grupiraj po..." + +#~ msgid "Apply" +#~ msgstr "Primjeni" diff --git a/connector/i18n/hr_HR.po b/connector/i18n/hr_HR.po new file mode 100644 index 000000000..a0c3df488 --- /dev/null +++ b/connector/i18n/hr_HR.po @@ -0,0 +1,79 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * connector +# +# Translators: +# OCA Transbot , 2018 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 11.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-01-05 16:56+0000\n" +"PO-Revision-Date: 2018-01-05 16:56+0000\n" +"Last-Translator: OCA Transbot , 2018\n" +"Language-Team: Croatian (Croatia) (https://www.transifex.com/oca/teams/23907/" +"hr_HR/)\n" +"Language: hr_HR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" + +#. module: connector +#: model:ir.module.category,name:connector.module_category_connector +msgid "Connector" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_connector_backend +msgid "Connector Backend" +msgstr "" + +#. module: connector +#: model:res.groups,name:connector.group_connector_manager +msgid "Connector Manager" +msgstr "" + +#. module: connector +#: model:ir.ui.menu,name:connector.menu_connector +#: model:ir.ui.menu,name:connector.menu_connector_root +#: model_terms:ir.ui.view,arch_db:connector.view_partner_connector_form +msgid "Connectors" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_external_binding +msgid "External Binding (abstract)" +msgstr "" + +#. module: connector +#: model:ir.model.fields,field_description:connector.field_external_binding__sync_date +msgid "Last synchronization date" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Nothing to export." +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_queue_job +msgid "Queue Job" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Record exported with ID %s on Backend." +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/models/queue_job.py:0 +#, python-format +msgid "Related Record" +msgstr "" diff --git a/connector/i18n/hu.po b/connector/i18n/hu.po new file mode 100644 index 000000000..5e494ae6e --- /dev/null +++ b/connector/i18n/hu.po @@ -0,0 +1,146 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * connector +# +# Translators: +# OCA Transbot , 2018 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 11.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-01-05 16:56+0000\n" +"PO-Revision-Date: 2018-01-05 16:56+0000\n" +"Last-Translator: OCA Transbot , 2018\n" +"Language-Team: Hungarian (https://www.transifex.com/oca/teams/23907/hu/)\n" +"Language: hu\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: connector +#: model:ir.module.category,name:connector.module_category_connector +msgid "Connector" +msgstr "Csatoló" + +#. module: connector +#: model:ir.model,name:connector.model_connector_backend +msgid "Connector Backend" +msgstr "" + +#. module: connector +#: model:res.groups,name:connector.group_connector_manager +msgid "Connector Manager" +msgstr "Csatoló beállítás" + +#. module: connector +#: model:ir.ui.menu,name:connector.menu_connector +#: model:ir.ui.menu,name:connector.menu_connector_root +#: model_terms:ir.ui.view,arch_db:connector.view_partner_connector_form +msgid "Connectors" +msgstr "Csatolók" + +#. module: connector +#: model:ir.model,name:connector.model_external_binding +msgid "External Binding (abstract)" +msgstr "Külső csatolás (absztract)" + +#. module: connector +#: model:ir.model.fields,field_description:connector.field_external_binding__sync_date +msgid "Last synchronization date" +msgstr "Utolsó szinkronizáció dátuma" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Nothing to export." +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_queue_job +msgid "Queue Job" +msgstr "Sorbanálló feladatok" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Record exported with ID %s on Backend." +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/models/queue_job.py:0 +#, python-format +msgid "Related Record" +msgstr "" + +#~ msgid "Cancel" +#~ msgstr "Mégsem" + +#~ msgid "Checkpoint" +#~ msgstr "Ellenőrzőpont" + +#~ msgid "Checkpoints" +#~ msgstr "Ellenörző pontok" + +#~ msgid "Checkpoints Review" +#~ msgstr "Ellenörzőpontok felülvizsgálata" + +#~ msgid "Click on the" +#~ msgstr "Kattintson erre" + +#~ msgid "Connector Checkpoint" +#~ msgstr "Csatoló ellenörzőpont" + +#~ msgid "Group By..." +#~ msgstr "Csoportosítás ezzel..." + +#~ msgid "Imported from" +#~ msgstr "Innen importált" + +#~ msgid "Model" +#~ msgstr "Modell, minta" + +#~ msgid "Need Review" +#~ msgstr "Felülvizsgálat szükséges" + +#~ msgid "Record ID" +#~ msgstr "Rekordazonosító ID" + +#~ msgid "Review Checkpoints" +#~ msgstr "Ellenörzőpontok felülvizsgálata" + +#~ msgid "Reviewed" +#~ msgstr "Leellenörzött" + +#~ msgid "Set as reviewed" +#~ msgstr "Leellenörzöttnek jelölt" + +#~ msgid "Status" +#~ msgstr "Állapot" + +#~ msgid "The record has been imported from this backend" +#~ msgstr "Erről a végpontról importált rekord" + +#~ msgid "The selected checkpoints will be set as reviewed." +#~ msgstr "A kiválasztott ellenörzőpont leellenörzőttként nyilvántartva." + +#~ msgid "to verify it:" +#~ msgstr "ezt ellenőrizni:" + +#~ msgid "Apply" +#~ msgstr "Alkalmaz" + +#~ msgid "Backends" +#~ msgstr "Háttérprogramok" + +#~ msgid "Configure Connector" +#~ msgstr "Csatlakozó beállítása" + +#~ msgid "Open Connector Menu" +#~ msgstr "Csatoló menü megnyitása" + +#~ msgid "or" +#~ msgstr "vagy" diff --git a/connector/i18n/it.po b/connector/i18n/it.po new file mode 100644 index 000000000..91d2aa3d3 --- /dev/null +++ b/connector/i18n/it.po @@ -0,0 +1,138 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * connector +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-03-10 03:36+0000\n" +"PO-Revision-Date: 2024-02-12 11:34+0000\n" +"Last-Translator: mymage \n" +"Language-Team: Italian (https://www.transifex.com/oca/teams/23907/it/)\n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.17\n" + +#. module: connector +#: model:ir.module.category,name:connector.module_category_connector +msgid "Connector" +msgstr "Connettore" + +#. module: connector +#: model:ir.model,name:connector.model_connector_backend +msgid "Connector Backend" +msgstr "Connettore backend" + +#. module: connector +#: model:res.groups,name:connector.group_connector_manager +msgid "Connector Manager" +msgstr "Gestore connettore" + +#. module: connector +#: model:ir.ui.menu,name:connector.menu_connector +#: model:ir.ui.menu,name:connector.menu_connector_root +#: model_terms:ir.ui.view,arch_db:connector.view_partner_connector_form +msgid "Connectors" +msgstr "Connettori" + +#. module: connector +#: model:ir.model,name:connector.model_external_binding +msgid "External Binding (abstract)" +msgstr "Collegamento esterno (astratto)" + +#. module: connector +#: model:ir.model.fields,field_description:connector.field_external_binding__sync_date +msgid "Last synchronization date" +msgstr "Data ultima sincronizzazione" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Nothing to export." +msgstr "Niente da esportare." + +#. module: connector +#: model:ir.model,name:connector.model_queue_job +msgid "Queue Job" +msgstr "Lavoro in coda" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Record exported with ID %s on Backend." +msgstr "Il record è stato esportato con ID %s su backend." + +#. module: connector +#. odoo-python +#: code:addons/connector/models/queue_job.py:0 +#, python-format +msgid "Related Record" +msgstr "Record collegato" + +#~ msgid "Display Name" +#~ msgstr "Nome da visualizzare" + +#~ msgid "ID" +#~ msgstr "ID" + +#~ msgid "Last Modified on" +#~ msgstr "Ultima modifica il" + +#~ msgid "Cancel" +#~ msgstr "Annulla" + +#~ msgid "Checkpoints" +#~ msgstr "Checkpoints" + +#~ msgid "Checkpoints Review" +#~ msgstr "Revisione Checkpoints" + +#~ msgid "Connector Checkpoint" +#~ msgstr "Checkpoint Connettore" + +#~ msgid "Created by" +#~ msgstr "Creato da" + +#~ msgid "Created on" +#~ msgstr "Creato il" + +#~ msgid "Group By..." +#~ msgstr "Raggruppa per..." + +#~ msgid "Imported from" +#~ msgstr "Importato da" + +#~ msgid "Last Updated by" +#~ msgstr "Ultimo aggiornamento di" + +#~ msgid "Last Updated on" +#~ msgstr "Ultimo aggiornamento il" + +#~ msgid "Set as reviewed" +#~ msgstr "Imposta come revisionato" + +#~ msgid "The record has been imported from this backend" +#~ msgstr "Il record è stato importato da questo backend" + +#~ msgid "Apply" +#~ msgstr "Applica" + +#~ msgid "Backends" +#~ msgstr "Backends" + +#~ msgid "Configure Connector" +#~ msgstr "Configura Connettore" + +#~ msgid "Open Connector Menu" +#~ msgstr "Apre il menù del Connettore" + +#~ msgid "or" +#~ msgstr "o" diff --git a/connector/i18n/lt.po b/connector/i18n/lt.po new file mode 100644 index 000000000..08cfbd911 --- /dev/null +++ b/connector/i18n/lt.po @@ -0,0 +1,81 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * connector +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-03-10 03:36+0000\n" +"PO-Revision-Date: 2017-03-10 03:36+0000\n" +"Last-Translator: OCA Transbot , 2017\n" +"Language-Team: Lithuanian (https://www.transifex.com/oca/teams/23907/lt/)\n" +"Language: lt\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n" +"%100<10 || n%100>=20) ? 1 : 2);\n" + +#. module: connector +#: model:ir.module.category,name:connector.module_category_connector +msgid "Connector" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_connector_backend +msgid "Connector Backend" +msgstr "" + +#. module: connector +#: model:res.groups,name:connector.group_connector_manager +msgid "Connector Manager" +msgstr "" + +#. module: connector +#: model:ir.ui.menu,name:connector.menu_connector +#: model:ir.ui.menu,name:connector.menu_connector_root +#: model_terms:ir.ui.view,arch_db:connector.view_partner_connector_form +msgid "Connectors" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_external_binding +msgid "External Binding (abstract)" +msgstr "" + +#. module: connector +#: model:ir.model.fields,field_description:connector.field_external_binding__sync_date +msgid "Last synchronization date" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Nothing to export." +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_queue_job +msgid "Queue Job" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Record exported with ID %s on Backend." +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/models/queue_job.py:0 +#, python-format +msgid "Related Record" +msgstr "" + +#~ msgid "Cancel" +#~ msgstr "Atšaukti" diff --git a/connector/i18n/nl.po b/connector/i18n/nl.po new file mode 100644 index 000000000..eb8383612 --- /dev/null +++ b/connector/i18n/nl.po @@ -0,0 +1,146 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * connector +# +# Translators: +# OCA Transbot , 2018 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 11.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-01-05 16:56+0000\n" +"PO-Revision-Date: 2018-01-05 16:56+0000\n" +"Last-Translator: OCA Transbot , 2018\n" +"Language-Team: Dutch (https://www.transifex.com/oca/teams/23907/nl/)\n" +"Language: nl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: connector +#: model:ir.module.category,name:connector.module_category_connector +msgid "Connector" +msgstr "Connector" + +#. module: connector +#: model:ir.model,name:connector.model_connector_backend +msgid "Connector Backend" +msgstr "" + +#. module: connector +#: model:res.groups,name:connector.group_connector_manager +msgid "Connector Manager" +msgstr "Connector manager" + +#. module: connector +#: model:ir.ui.menu,name:connector.menu_connector +#: model:ir.ui.menu,name:connector.menu_connector_root +#: model_terms:ir.ui.view,arch_db:connector.view_partner_connector_form +msgid "Connectors" +msgstr "Connectors" + +#. module: connector +#: model:ir.model,name:connector.model_external_binding +msgid "External Binding (abstract)" +msgstr "External Binding (abstract)" + +#. module: connector +#: model:ir.model.fields,field_description:connector.field_external_binding__sync_date +msgid "Last synchronization date" +msgstr "Laatste synchronisatie datum" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Nothing to export." +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_queue_job +msgid "Queue Job" +msgstr "Geplande taken" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Record exported with ID %s on Backend." +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/models/queue_job.py:0 +#, python-format +msgid "Related Record" +msgstr "" + +#~ msgid "Cancel" +#~ msgstr "Annuleer" + +#~ msgid "Checkpoint" +#~ msgstr "Controlepunt" + +#~ msgid "Checkpoints" +#~ msgstr "Controlepunten" + +#~ msgid "Checkpoints Review" +#~ msgstr "Controlepunten controle" + +#~ msgid "Click on the" +#~ msgstr "Klik op de" + +#~ msgid "Connector Checkpoint" +#~ msgstr "Connector controlepunt" + +#~ msgid "Group By..." +#~ msgstr "Groepeer op..." + +#~ msgid "Imported from" +#~ msgstr "Geïmporteerd van" + +#~ msgid "Model" +#~ msgstr "Model" + +#~ msgid "Need Review" +#~ msgstr "Controle nodig" + +#~ msgid "Record ID" +#~ msgstr "Record-id" + +#~ msgid "Review Checkpoints" +#~ msgstr "Controleer controlepunten" + +#~ msgid "Reviewed" +#~ msgstr "Gecontroleerd" + +#~ msgid "Set as reviewed" +#~ msgstr "Stel in als gecontroleerd" + +#~ msgid "Status" +#~ msgstr "Status" + +#~ msgid "The record has been imported from this backend" +#~ msgstr "De regel is geïmporteerd vanuit deze backend" + +#~ msgid "The selected checkpoints will be set as reviewed." +#~ msgstr "De geselecteerde controlepunten worden ingesteld als gecontroleerd" + +#~ msgid "to verify it:" +#~ msgstr "om te controleren:" + +#~ msgid "Apply" +#~ msgstr "Toepassen" + +#~ msgid "Backends" +#~ msgstr "Backends" + +#~ msgid "Configure Connector" +#~ msgstr "Connector instellen" + +#~ msgid "Open Connector Menu" +#~ msgstr "Open connector menu" + +#~ msgid "or" +#~ msgstr "of" diff --git a/connector/i18n/nl_BE.po b/connector/i18n/nl_BE.po new file mode 100644 index 000000000..370979795 --- /dev/null +++ b/connector/i18n/nl_BE.po @@ -0,0 +1,81 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * connector +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-03-10 03:36+0000\n" +"PO-Revision-Date: 2017-03-10 03:36+0000\n" +"Last-Translator: OCA Transbot , 2017\n" +"Language-Team: Dutch (Belgium) (https://www.transifex.com/oca/teams/23907/" +"nl_BE/)\n" +"Language: nl_BE\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: connector +#: model:ir.module.category,name:connector.module_category_connector +msgid "Connector" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_connector_backend +msgid "Connector Backend" +msgstr "" + +#. module: connector +#: model:res.groups,name:connector.group_connector_manager +msgid "Connector Manager" +msgstr "" + +#. module: connector +#: model:ir.ui.menu,name:connector.menu_connector +#: model:ir.ui.menu,name:connector.menu_connector_root +#: model_terms:ir.ui.view,arch_db:connector.view_partner_connector_form +msgid "Connectors" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_external_binding +msgid "External Binding (abstract)" +msgstr "" + +#. module: connector +#: model:ir.model.fields,field_description:connector.field_external_binding__sync_date +msgid "Last synchronization date" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Nothing to export." +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_queue_job +msgid "Queue Job" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Record exported with ID %s on Backend." +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/models/queue_job.py:0 +#, python-format +msgid "Related Record" +msgstr "" + +#~ msgid "Cancel" +#~ msgstr "Annuleren" diff --git a/connector/i18n/pl.po b/connector/i18n/pl.po new file mode 100644 index 000000000..4dc86f5c3 --- /dev/null +++ b/connector/i18n/pl.po @@ -0,0 +1,82 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * connector +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-03-10 03:36+0000\n" +"PO-Revision-Date: 2017-03-10 03:36+0000\n" +"Last-Translator: OCA Transbot , 2017\n" +"Language-Team: Polish (https://www.transifex.com/oca/teams/23907/pl/)\n" +"Language: pl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n" +"%100<12 || n%100>=14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n" +"%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n" + +#. module: connector +#: model:ir.module.category,name:connector.module_category_connector +msgid "Connector" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_connector_backend +msgid "Connector Backend" +msgstr "" + +#. module: connector +#: model:res.groups,name:connector.group_connector_manager +msgid "Connector Manager" +msgstr "" + +#. module: connector +#: model:ir.ui.menu,name:connector.menu_connector +#: model:ir.ui.menu,name:connector.menu_connector_root +#: model_terms:ir.ui.view,arch_db:connector.view_partner_connector_form +msgid "Connectors" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_external_binding +msgid "External Binding (abstract)" +msgstr "" + +#. module: connector +#: model:ir.model.fields,field_description:connector.field_external_binding__sync_date +msgid "Last synchronization date" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Nothing to export." +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_queue_job +msgid "Queue Job" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Record exported with ID %s on Backend." +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/models/queue_job.py:0 +#, python-format +msgid "Related Record" +msgstr "" + +#~ msgid "Cancel" +#~ msgstr "Anuluj" diff --git a/connector/i18n/pt.po b/connector/i18n/pt.po new file mode 100644 index 000000000..eec627f62 --- /dev/null +++ b/connector/i18n/pt.po @@ -0,0 +1,95 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * connector +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-03-10 03:36+0000\n" +"PO-Revision-Date: 2017-03-10 03:36+0000\n" +"Last-Translator: OCA Transbot , 2017\n" +"Language-Team: Portuguese (https://www.transifex.com/oca/teams/23907/pt/)\n" +"Language: pt\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: connector +#: model:ir.module.category,name:connector.module_category_connector +msgid "Connector" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_connector_backend +msgid "Connector Backend" +msgstr "" + +#. module: connector +#: model:res.groups,name:connector.group_connector_manager +msgid "Connector Manager" +msgstr "" + +#. module: connector +#: model:ir.ui.menu,name:connector.menu_connector +#: model:ir.ui.menu,name:connector.menu_connector_root +#: model_terms:ir.ui.view,arch_db:connector.view_partner_connector_form +msgid "Connectors" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_external_binding +msgid "External Binding (abstract)" +msgstr "" + +#. module: connector +#: model:ir.model.fields,field_description:connector.field_external_binding__sync_date +msgid "Last synchronization date" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Nothing to export." +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_queue_job +msgid "Queue Job" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Record exported with ID %s on Backend." +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/models/queue_job.py:0 +#, python-format +msgid "Related Record" +msgstr "" + +#~ msgid "ID" +#~ msgstr "ID" + +#~ msgid "Cancel" +#~ msgstr "Cancelar" + +#~ msgid "Created by" +#~ msgstr "Criado por" + +#~ msgid "Created on" +#~ msgstr "Criado em" + +#~ msgid "Last Updated by" +#~ msgstr "Atualizado pela última vez por" + +#~ msgid "Last Updated on" +#~ msgstr "Atualizado pela última vez em" diff --git a/connector/i18n/pt_BR.po b/connector/i18n/pt_BR.po new file mode 100644 index 000000000..3123c700e --- /dev/null +++ b/connector/i18n/pt_BR.po @@ -0,0 +1,324 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * connector +# +# Translators: +# OCA Transbot , 2018 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 11.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-01-05 16:56+0000\n" +"PO-Revision-Date: 2020-03-21 20:14+0000\n" +"Last-Translator: Rodrigo Macedo \n" +"Language-Team: Portuguese (Brazil) (https://www.transifex.com/oca/" +"teams/23907/pt_BR/)\n" +"Language: pt_BR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 3.10\n" + +#. module: connector +#: model:ir.module.category,name:connector.module_category_connector +msgid "Connector" +msgstr "Conector" + +#. module: connector +#: model:ir.model,name:connector.model_connector_backend +msgid "Connector Backend" +msgstr "Backend do conector" + +#. module: connector +#: model:res.groups,name:connector.group_connector_manager +msgid "Connector Manager" +msgstr "Gerenciador do conector" + +#. module: connector +#: model:ir.ui.menu,name:connector.menu_connector +#: model:ir.ui.menu,name:connector.menu_connector_root +#: model_terms:ir.ui.view,arch_db:connector.view_partner_connector_form +msgid "Connectors" +msgstr "Conectores" + +#. module: connector +#: model:ir.model,name:connector.model_external_binding +msgid "External Binding (abstract)" +msgstr "Ligações externas (resumo)" + +#. module: connector +#: model:ir.model.fields,field_description:connector.field_external_binding__sync_date +msgid "Last synchronization date" +msgstr "Última data de sincronização" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Nothing to export." +msgstr "Nada para exportar." + +#. module: connector +#: model:ir.model,name:connector.model_queue_job +msgid "Queue Job" +msgstr "Fila de tarefas" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Record exported with ID %s on Backend." +msgstr "Registro exportado com o ID %s no back-end." + +#. module: connector +#. odoo-python +#: code:addons/connector/models/queue_job.py:0 +#, python-format +msgid "Related Record" +msgstr "Registro relacionado" + +#~ msgid "Display Name" +#~ msgstr "Exibir Nome" + +#~ msgid "ID" +#~ msgstr "ID" + +#~ msgid "Last Modified on" +#~ msgstr "Última Modificação em" + +#~ msgid "A %s needs a review." +#~ msgstr "Um %s necessita revisão." + +#~ msgid "Action Needed" +#~ msgstr "Ação Necessária" + +#~ msgid "Activities" +#~ msgstr "Atividades" + +#~ msgid "Activity Exception Decoration" +#~ msgstr "Decoração de Exceção de Atividade" + +#~ msgid "Activity State" +#~ msgstr "Estado da Atividade" + +#~ msgid "Attachment Count" +#~ msgstr "Conta de Anexos" + +#~ msgid "Cancel" +#~ msgstr "Cancelar" + +#~ msgid "Checkpoint" +#~ msgstr "Ponto de checagem" + +#~ msgid "Checkpoints" +#~ msgstr "Pontos de checagem" + +#~ msgid "Checkpoints Review" +#~ msgstr "Revisão de pontos de checagem" + +#~ msgid "Click on the" +#~ msgstr "Clique na" + +#~ msgid "Company" +#~ msgstr "Empresa" + +#~ msgid "Connector Checkpoint" +#~ msgstr "Ponto de checagem conector" + +#~ msgid "Created by" +#~ msgstr "Criado por" + +#~ msgid "Created on" +#~ msgstr "Criado em" + +#~ msgid "Followers" +#~ msgstr "Seguidores" + +#~ msgid "Followers (Channels)" +#~ msgstr "Seguidores (Canais)" + +#~ msgid "Followers (Partners)" +#~ msgstr "Seguidores (Parceiros)" + +#~ msgid "Group By..." +#~ msgstr "Agrupar por .." + +#~ msgid "Icon" +#~ msgstr "Ícone" + +#~ msgid "Icon to indicate an exception activity." +#~ msgstr "Ícone para indicar uma atividade de exceção." + +#~ msgid "If checked, new messages require your attention." +#~ msgstr "Se marcada, novas mensagens requerem sua atenção." + +#~ msgid "If checked, some messages have a delivery error." +#~ msgstr "Se marcada, algumas mensagens tem um erro de entrega." + +#~ msgid "Imported from" +#~ msgstr "Importado de" + +#~ msgid "Is Follower" +#~ msgstr "É Seguidor" + +#~ msgid "Last Updated by" +#~ msgstr "Última atualização por" + +#~ msgid "Last Updated on" +#~ msgstr "Atualizado pela última vez em" + +#~ msgid "Main Attachment" +#~ msgstr "Anexo Principal" + +#~ msgid "Message Delivery error" +#~ msgstr "Mensagem de erro de entrega" + +#~ msgid "Messages" +#~ msgstr "Mensagens" + +#~ msgid "Model" +#~ msgstr "Modelo" + +#~ msgid "Name of the record to review" +#~ msgstr "Nome do registro para revisar" + +#~ msgid "Need Review" +#~ msgstr "Necessita revisão" + +#~ msgid "Next Activity Deadline" +#~ msgstr "Próximo prazo de atividade" + +#~ msgid "Next Activity Summary" +#~ msgstr "Próximo resumo da atividade" + +#~ msgid "Next Activity Type" +#~ msgstr "Próximo tipo de atividade" + +#~ msgid "No record to check." +#~ msgstr "sem registro para checar." + +#~ msgid "Number of Actions" +#~ msgstr "Número de Ações" + +#~ msgid "Number of errors" +#~ msgstr "Número de erros" + +#~ msgid "Number of messages which requires an action" +#~ msgstr "Número de mensagens que requerem uma ação" + +#~ msgid "Number of messages with delivery error" +#~ msgstr "Número de mensagens com erro de entrega" + +#~ msgid "Number of unread messages" +#~ msgstr "Número de mensagens não lidas" + +#~ msgid "Record" +#~ msgstr "Registro" + +#~ msgid "Record ID" +#~ msgstr "ID do registro" + +#~ msgid "Record Name" +#~ msgstr "Nome Registro" + +#~ msgid "Responsible User" +#~ msgstr "Usuário Responsável" + +#~ msgid "Review Checkpoints" +#~ msgstr "Revisão dos pontos de checagem" + +#~ msgid "Reviewed" +#~ msgstr "Revisado" + +#~ msgid "SMS Delivery error" +#~ msgstr "SMS de erro de entrega" + +#~ msgid "Set as reviewed" +#~ msgstr "Marcar como revisado" + +#~ msgid "Status" +#~ msgstr "Situação" + +#~ msgid "" +#~ "Status based on activities\n" +#~ "Overdue: Due date is already passed\n" +#~ "Today: Activity date is today\n" +#~ "Planned: Future activities." +#~ msgstr "" +#~ "Status baseado em atividades\n" +#~ "Em atraso: a data de vencimento já passou\n" +#~ "Hoje: a data da atividade é hoje\n" +#~ "Planejado: atividades futuras." + +#~ msgid "" +#~ "The connectors list the new records to verify\n" +#~ " based on their type. Only some need a manual\n" +#~ " review." +#~ msgstr "" +#~ "Os conectores listam os novos registros para verificar\n" +#~ " com base no seu tipo. Apenas alguns precisam de um " +#~ "manual\n" +#~ " Reveja." + +#~ msgid "The record has been imported from this backend" +#~ msgstr "O registro foi importado deste backend" + +#~ msgid "The record to review." +#~ msgstr "O registro para revisar." + +#~ msgid "The selected checkpoints will be set as reviewed." +#~ msgstr "O pontos de checagem selecionados vão ser marcados como revisados." + +#~ msgid "Type of the exception activity on record." +#~ msgstr "Tipo da atividade de exceção registrada." + +#~ msgid "Unread Messages" +#~ msgstr "Mensagens não lidas" + +#~ msgid "Unread Messages Counter" +#~ msgstr "Contador de mensagens não lidas" + +#~ msgid "" +#~ "When a connector imports new records which have\n" +#~ " configuration or reviews to do manually, they\n" +#~ " will appear in this list. Once a record has been\n" +#~ " checked, click on the 'Reviewed' button." +#~ msgstr "" +#~ "Quando um conector importa novos registros que\n" +#~ " configuração ou revisões para fazer manualmente, eles\n" +#~ " aparecerá nesta lista. Depois de um registro ter sido\n" +#~ " marcado, clique no botão \"Revisto\"." + +#~ msgid "to verify it:" +#~ msgstr "para verificar isto:" + +#~ msgid "If checked new messages require your attention." +#~ msgstr "Se marcada, novas mensagens requerem sua atenção." + +#~ msgid "Overdue" +#~ msgstr "Atrasado(a)" + +#~ msgid "Planned" +#~ msgstr "Planejada" + +#~ msgid "Today" +#~ msgstr "Hoje" + +#~ msgid "Apply" +#~ msgstr "Aplicar" + +#~ msgid "Backends" +#~ msgstr "Back-ends" + +#~ msgid "Configure Connector" +#~ msgstr "Configurar conector" + +#~ msgid "Connector Configuration" +#~ msgstr "Configuração do conector" + +#~ msgid "Open Connector Menu" +#~ msgstr "Abrir menu do conector" + +#~ msgid "or" +#~ msgstr "ou" diff --git a/connector/i18n/pt_PT.po b/connector/i18n/pt_PT.po new file mode 100644 index 000000000..1716b39a1 --- /dev/null +++ b/connector/i18n/pt_PT.po @@ -0,0 +1,99 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * connector +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-03-10 03:36+0000\n" +"PO-Revision-Date: 2017-03-10 03:36+0000\n" +"Last-Translator: OCA Transbot , 2017\n" +"Language-Team: Portuguese (Portugal) (https://www.transifex.com/oca/" +"teams/23907/pt_PT/)\n" +"Language: pt_PT\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: connector +#: model:ir.module.category,name:connector.module_category_connector +msgid "Connector" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_connector_backend +msgid "Connector Backend" +msgstr "" + +#. module: connector +#: model:res.groups,name:connector.group_connector_manager +msgid "Connector Manager" +msgstr "" + +#. module: connector +#: model:ir.ui.menu,name:connector.menu_connector +#: model:ir.ui.menu,name:connector.menu_connector_root +#: model_terms:ir.ui.view,arch_db:connector.view_partner_connector_form +msgid "Connectors" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_external_binding +msgid "External Binding (abstract)" +msgstr "" + +#. module: connector +#: model:ir.model.fields,field_description:connector.field_external_binding__sync_date +msgid "Last synchronization date" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Nothing to export." +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_queue_job +msgid "Queue Job" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Record exported with ID %s on Backend." +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/models/queue_job.py:0 +#, python-format +msgid "Related Record" +msgstr "" + +#~ msgid "ID" +#~ msgstr "ID" + +#~ msgid "Cancel" +#~ msgstr "Cancelar" + +#~ msgid "Created by" +#~ msgstr "Criado por" + +#~ msgid "Created on" +#~ msgstr "Criado em" + +#~ msgid "Last Updated by" +#~ msgstr "Atualizado pela última vez por" + +#~ msgid "Last Updated on" +#~ msgstr "Atualizado pela última vez em" + +#~ msgid "Status" +#~ msgstr "Estado" diff --git a/connector/i18n/ro.po b/connector/i18n/ro.po new file mode 100644 index 000000000..c3f1dfc8d --- /dev/null +++ b/connector/i18n/ro.po @@ -0,0 +1,84 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * connector +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-03-10 03:36+0000\n" +"PO-Revision-Date: 2017-03-10 03:36+0000\n" +"Last-Translator: OCA Transbot , 2017\n" +"Language-Team: Romanian (https://www.transifex.com/oca/teams/23907/ro/)\n" +"Language: ro\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?" +"2:1));\n" + +#. module: connector +#: model:ir.module.category,name:connector.module_category_connector +msgid "Connector" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_connector_backend +msgid "Connector Backend" +msgstr "" + +#. module: connector +#: model:res.groups,name:connector.group_connector_manager +msgid "Connector Manager" +msgstr "" + +#. module: connector +#: model:ir.ui.menu,name:connector.menu_connector +#: model:ir.ui.menu,name:connector.menu_connector_root +#: model_terms:ir.ui.view,arch_db:connector.view_partner_connector_form +msgid "Connectors" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_external_binding +msgid "External Binding (abstract)" +msgstr "" + +#. module: connector +#: model:ir.model.fields,field_description:connector.field_external_binding__sync_date +msgid "Last synchronization date" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Nothing to export." +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_queue_job +msgid "Queue Job" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Record exported with ID %s on Backend." +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/models/queue_job.py:0 +#, python-format +msgid "Related Record" +msgstr "" + +#~ msgid "Cancel" +#~ msgstr "Anuleaza" + +#~ msgid "Apply" +#~ msgstr "Aplică" diff --git a/connector/i18n/ru.po b/connector/i18n/ru.po new file mode 100644 index 000000000..a2df444b9 --- /dev/null +++ b/connector/i18n/ru.po @@ -0,0 +1,82 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * connector +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-03-10 03:36+0000\n" +"PO-Revision-Date: 2017-03-10 03:36+0000\n" +"Last-Translator: OCA Transbot , 2017\n" +"Language-Team: Russian (https://www.transifex.com/oca/teams/23907/ru/)\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n" +"%100>=11 && n%100<=14)? 2 : 3);\n" + +#. module: connector +#: model:ir.module.category,name:connector.module_category_connector +msgid "Connector" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_connector_backend +msgid "Connector Backend" +msgstr "" + +#. module: connector +#: model:res.groups,name:connector.group_connector_manager +msgid "Connector Manager" +msgstr "" + +#. module: connector +#: model:ir.ui.menu,name:connector.menu_connector +#: model:ir.ui.menu,name:connector.menu_connector_root +#: model_terms:ir.ui.view,arch_db:connector.view_partner_connector_form +msgid "Connectors" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_external_binding +msgid "External Binding (abstract)" +msgstr "" + +#. module: connector +#: model:ir.model.fields,field_description:connector.field_external_binding__sync_date +msgid "Last synchronization date" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Nothing to export." +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_queue_job +msgid "Queue Job" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Record exported with ID %s on Backend." +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/models/queue_job.py:0 +#, python-format +msgid "Related Record" +msgstr "" + +#~ msgid "Cancel" +#~ msgstr "Отменена" diff --git a/connector/i18n/sl.po b/connector/i18n/sl.po new file mode 100644 index 000000000..de2916776 --- /dev/null +++ b/connector/i18n/sl.po @@ -0,0 +1,174 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * connector +# +# Translators: +# OCA Transbot , 2018 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 11.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-01-05 16:56+0000\n" +"PO-Revision-Date: 2018-01-05 16:56+0000\n" +"Last-Translator: OCA Transbot , 2018\n" +"Language-Team: Slovenian (https://www.transifex.com/oca/teams/23907/sl/)\n" +"Language: sl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n" +"%100==4 ? 2 : 3);\n" + +#. module: connector +#: model:ir.module.category,name:connector.module_category_connector +msgid "Connector" +msgstr "Povezovalnik" + +#. module: connector +#: model:ir.model,name:connector.model_connector_backend +msgid "Connector Backend" +msgstr "Ozadje povezovalnika" + +#. module: connector +#: model:res.groups,name:connector.group_connector_manager +msgid "Connector Manager" +msgstr "Upravitelj povezovalnika" + +#. module: connector +#: model:ir.ui.menu,name:connector.menu_connector +#: model:ir.ui.menu,name:connector.menu_connector_root +#: model_terms:ir.ui.view,arch_db:connector.view_partner_connector_form +msgid "Connectors" +msgstr "Konektorji" + +#. module: connector +#: model:ir.model,name:connector.model_external_binding +msgid "External Binding (abstract)" +msgstr "Zunanja povezava (povzetek)" + +#. module: connector +#: model:ir.model.fields,field_description:connector.field_external_binding__sync_date +msgid "Last synchronization date" +msgstr "Datum zadnje sinhronizacije" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Nothing to export." +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_queue_job +msgid "Queue Job" +msgstr "Delo čakalne vrste" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Record exported with ID %s on Backend." +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/models/queue_job.py:0 +#, python-format +msgid "Related Record" +msgstr "Povezani zapis" + +#~ msgid "Display Name" +#~ msgstr "Prikazni naziv" + +#~ msgid "ID" +#~ msgstr "ID" + +#~ msgid "Last Modified on" +#~ msgstr "Zadnjič spremenjeno" + +#~ msgid "A %s needs a review." +#~ msgstr "Potrebna je revizija %s ." + +#~ msgid "Cancel" +#~ msgstr "Preklic" + +#~ msgid "Checkpoint" +#~ msgstr "Kontrolna točka" + +#~ msgid "Checkpoints" +#~ msgstr "Kontrolne točke" + +#~ msgid "Checkpoints Review" +#~ msgstr "Preverjanje kontrolnih točk" + +#~ msgid "Click on the" +#~ msgstr "Kliknite na" + +#~ msgid "Connector Checkpoint" +#~ msgstr "Kontrolna točka povezovalnika" + +#~ msgid "Created by" +#~ msgstr "Ustvaril" + +#~ msgid "Created on" +#~ msgstr "Ustvarjeno" + +#~ msgid "Group By..." +#~ msgstr "Združi po..." + +#~ msgid "Imported from" +#~ msgstr "Uvoženo iz" + +#~ msgid "Last Updated by" +#~ msgstr "Zadnji posodobil" + +#~ msgid "Last Updated on" +#~ msgstr "Zadnjič posodobljeno" + +#~ msgid "Model" +#~ msgstr "Model" + +#~ msgid "Need Review" +#~ msgstr "Potrebna revizija" + +#~ msgid "Record ID" +#~ msgstr "ID zapisa" + +#~ msgid "Review Checkpoints" +#~ msgstr "Pregled kontrolnih točk" + +#~ msgid "Reviewed" +#~ msgstr "Pregledano" + +#~ msgid "Set as reviewed" +#~ msgstr "Nastavi kot pregledano" + +#~ msgid "Status" +#~ msgstr "Status" + +#~ msgid "The record has been imported from this backend" +#~ msgstr "Zapis je bil uvožen iz tega ozadja." + +#~ msgid "The selected checkpoints will be set as reviewed." +#~ msgstr "Izbrane kontrolne točke bodo označene kot pregledane." + +#~ msgid "to verify it:" +#~ msgstr "za preverjanje:" + +#~ msgid "Apply" +#~ msgstr "Uporabi" + +#~ msgid "Backends" +#~ msgstr "Ozadja" + +#~ msgid "Configure Connector" +#~ msgstr "Nastavitve povezovalnika" + +#~ msgid "Connector Configuration" +#~ msgstr "Nastavitve povezovalnika" + +#~ msgid "Open Connector Menu" +#~ msgstr "Odpri meni povezovalnika" + +#~ msgid "or" +#~ msgstr "ali" diff --git a/connector/i18n/th.po b/connector/i18n/th.po new file mode 100644 index 000000000..ca61007be --- /dev/null +++ b/connector/i18n/th.po @@ -0,0 +1,80 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * connector +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-03-10 03:36+0000\n" +"PO-Revision-Date: 2017-03-10 03:36+0000\n" +"Last-Translator: OCA Transbot , 2017\n" +"Language-Team: Thai (https://www.transifex.com/oca/teams/23907/th/)\n" +"Language: th\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#. module: connector +#: model:ir.module.category,name:connector.module_category_connector +msgid "Connector" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_connector_backend +msgid "Connector Backend" +msgstr "" + +#. module: connector +#: model:res.groups,name:connector.group_connector_manager +msgid "Connector Manager" +msgstr "" + +#. module: connector +#: model:ir.ui.menu,name:connector.menu_connector +#: model:ir.ui.menu,name:connector.menu_connector_root +#: model_terms:ir.ui.view,arch_db:connector.view_partner_connector_form +msgid "Connectors" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_external_binding +msgid "External Binding (abstract)" +msgstr "" + +#. module: connector +#: model:ir.model.fields,field_description:connector.field_external_binding__sync_date +msgid "Last synchronization date" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Nothing to export." +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_queue_job +msgid "Queue Job" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Record exported with ID %s on Backend." +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/models/queue_job.py:0 +#, python-format +msgid "Related Record" +msgstr "" + +#~ msgid "Cancel" +#~ msgstr "ยกเลิก" diff --git a/connector/i18n/tr.po b/connector/i18n/tr.po new file mode 100644 index 000000000..3266d3fb3 --- /dev/null +++ b/connector/i18n/tr.po @@ -0,0 +1,95 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * connector +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-03-10 03:36+0000\n" +"PO-Revision-Date: 2017-03-10 03:36+0000\n" +"Last-Translator: OCA Transbot , 2017\n" +"Language-Team: Turkish (https://www.transifex.com/oca/teams/23907/tr/)\n" +"Language: tr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#. module: connector +#: model:ir.module.category,name:connector.module_category_connector +msgid "Connector" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_connector_backend +msgid "Connector Backend" +msgstr "" + +#. module: connector +#: model:res.groups,name:connector.group_connector_manager +msgid "Connector Manager" +msgstr "" + +#. module: connector +#: model:ir.ui.menu,name:connector.menu_connector +#: model:ir.ui.menu,name:connector.menu_connector_root +#: model_terms:ir.ui.view,arch_db:connector.view_partner_connector_form +msgid "Connectors" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_external_binding +msgid "External Binding (abstract)" +msgstr "" + +#. module: connector +#: model:ir.model.fields,field_description:connector.field_external_binding__sync_date +msgid "Last synchronization date" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Nothing to export." +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_queue_job +msgid "Queue Job" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Record exported with ID %s on Backend." +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/models/queue_job.py:0 +#, python-format +msgid "Related Record" +msgstr "" + +#~ msgid "ID" +#~ msgstr "ID" + +#~ msgid "Cancel" +#~ msgstr "Vazgeç" + +#~ msgid "Created by" +#~ msgstr "Oluşturan" + +#~ msgid "Created on" +#~ msgstr "Oluşturuldu" + +#~ msgid "Last Updated by" +#~ msgstr "Son güncelleyen" + +#~ msgid "Last Updated on" +#~ msgstr "Son güncelleme" diff --git a/connector/i18n/vi.po b/connector/i18n/vi.po new file mode 100644 index 000000000..20f3664b8 --- /dev/null +++ b/connector/i18n/vi.po @@ -0,0 +1,80 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * connector +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-03-10 03:36+0000\n" +"PO-Revision-Date: 2017-03-10 03:36+0000\n" +"Last-Translator: OCA Transbot , 2017\n" +"Language-Team: Vietnamese (https://www.transifex.com/oca/teams/23907/vi/)\n" +"Language: vi\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#. module: connector +#: model:ir.module.category,name:connector.module_category_connector +msgid "Connector" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_connector_backend +msgid "Connector Backend" +msgstr "" + +#. module: connector +#: model:res.groups,name:connector.group_connector_manager +msgid "Connector Manager" +msgstr "" + +#. module: connector +#: model:ir.ui.menu,name:connector.menu_connector +#: model:ir.ui.menu,name:connector.menu_connector_root +#: model_terms:ir.ui.view,arch_db:connector.view_partner_connector_form +msgid "Connectors" +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_external_binding +msgid "External Binding (abstract)" +msgstr "" + +#. module: connector +#: model:ir.model.fields,field_description:connector.field_external_binding__sync_date +msgid "Last synchronization date" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Nothing to export." +msgstr "" + +#. module: connector +#: model:ir.model,name:connector.model_queue_job +msgid "Queue Job" +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Record exported with ID %s on Backend." +msgstr "" + +#. module: connector +#. odoo-python +#: code:addons/connector/models/queue_job.py:0 +#, python-format +msgid "Related Record" +msgstr "" + +#~ msgid "Cancel" +#~ msgstr "Hủy bỏ" diff --git a/connector/i18n/zh_CN.po b/connector/i18n/zh_CN.po new file mode 100644 index 000000000..b30c45096 --- /dev/null +++ b/connector/i18n/zh_CN.po @@ -0,0 +1,320 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * connector +# +# Translators: +# OCA Transbot , 2018 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 11.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-01-05 16:56+0000\n" +"PO-Revision-Date: 2020-07-08 05:19+0000\n" +"Last-Translator: 黎伟杰 <674416404@qq.com>\n" +"Language-Team: Chinese (China) (https://www.transifex.com/oca/teams/23907/" +"zh_CN/)\n" +"Language: zh_CN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 3.10\n" + +#. module: connector +#: model:ir.module.category,name:connector.module_category_connector +msgid "Connector" +msgstr "连接器" + +#. module: connector +#: model:ir.model,name:connector.model_connector_backend +msgid "Connector Backend" +msgstr "连接器后端" + +#. module: connector +#: model:res.groups,name:connector.group_connector_manager +msgid "Connector Manager" +msgstr "连接器管理" + +#. module: connector +#: model:ir.ui.menu,name:connector.menu_connector +#: model:ir.ui.menu,name:connector.menu_connector_root +#: model_terms:ir.ui.view,arch_db:connector.view_partner_connector_form +msgid "Connectors" +msgstr "连接器" + +#. module: connector +#: model:ir.model,name:connector.model_external_binding +msgid "External Binding (abstract)" +msgstr "外部绑定" + +#. module: connector +#: model:ir.model.fields,field_description:connector.field_external_binding__sync_date +msgid "Last synchronization date" +msgstr "最后同步日期" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Nothing to export." +msgstr "无需输出。" + +#. module: connector +#: model:ir.model,name:connector.model_queue_job +msgid "Queue Job" +msgstr "队列中作业" + +#. module: connector +#. odoo-python +#: code:addons/connector/components/synchronizer.py:0 +#, python-format +msgid "Record exported with ID %s on Backend." +msgstr "已在后端导出ID为%s的记录。" + +#. module: connector +#. odoo-python +#: code:addons/connector/models/queue_job.py:0 +#, python-format +msgid "Related Record" +msgstr "相关记录" + +#~ msgid "Display Name" +#~ msgstr "显示名称" + +#~ msgid "ID" +#~ msgstr "ID" + +#~ msgid "Last Modified on" +#~ msgstr "最后修改日" + +#~ msgid "A %s needs a review." +#~ msgstr "一个 %s 需要审核。" + +#~ msgid "Action Needed" +#~ msgstr "需要的操作" + +#~ msgid "Activities" +#~ msgstr "活动" + +#~ msgid "Activity Exception Decoration" +#~ msgstr "活动异常装饰" + +#~ msgid "Activity State" +#~ msgstr "活动状态" + +#~ msgid "Attachment Count" +#~ msgstr "附件数量" + +#~ msgid "Cancel" +#~ msgstr "取消" + +#~ msgid "Checkpoint" +#~ msgstr "检查点" + +#~ msgid "Checkpoints" +#~ msgstr "检查点" + +#~ msgid "Checkpoints Review" +#~ msgstr "检查点视图" + +#~ msgid "Click on the" +#~ msgstr "单击" + +#~ msgid "Company" +#~ msgstr "公司" + +#~ msgid "Connector Checkpoint" +#~ msgstr "连接器检查点" + +#~ msgid "Created by" +#~ msgstr "创建者" + +#~ msgid "Created on" +#~ msgstr "创建时间" + +#~ msgid "Followers" +#~ msgstr "关注者" + +#~ msgid "Followers (Channels)" +#~ msgstr "关注者(频道)" + +#~ msgid "Followers (Partners)" +#~ msgstr "关注者(业务伙伴)" + +#~ msgid "Group By..." +#~ msgstr "分组..." + +#~ msgid "Icon" +#~ msgstr "图标" + +#~ msgid "Icon to indicate an exception activity." +#~ msgstr "表示异常活动的图标。" + +#~ msgid "If checked, new messages require your attention." +#~ msgstr "如果选中,则需要您注意新消息。" + +#~ msgid "If checked, some messages have a delivery error." +#~ msgstr "如果选中,则某些邮件会发送传递错误。" + +#~ msgid "Imported from" +#~ msgstr "导入自" + +#~ msgid "Is Follower" +#~ msgstr "是关注者" + +#~ msgid "Last Updated by" +#~ msgstr "最后更新者" + +#~ msgid "Last Updated on" +#~ msgstr "最后更新时间" + +#~ msgid "Main Attachment" +#~ msgstr "附件" + +#~ msgid "Message Delivery error" +#~ msgstr "消息递送错误" + +#~ msgid "Messages" +#~ msgstr "消息" + +#~ msgid "Model" +#~ msgstr "模型" + +#~ msgid "Name of the record to review" +#~ msgstr "要审核的记录的名称" + +#~ msgid "Need Review" +#~ msgstr "需要审阅" + +#~ msgid "Next Activity Deadline" +#~ msgstr "下一活动截止日期" + +#~ msgid "Next Activity Summary" +#~ msgstr "下一个活动摘要" + +#~ msgid "Next Activity Type" +#~ msgstr "下一个活动类型" + +#~ msgid "No record to check." +#~ msgstr "没有记录要检查。" + +#~ msgid "Number of Actions" +#~ msgstr "操作次数" + +#~ msgid "Number of errors" +#~ msgstr "错误数量" + +#~ msgid "Number of messages which requires an action" +#~ msgstr "需要操作的消息数" + +#~ msgid "Number of messages with delivery error" +#~ msgstr "发送错误的消息数量" + +#~ msgid "Number of unread messages" +#~ msgstr "未读消息数量" + +#~ msgid "Record" +#~ msgstr "记录" + +#~ msgid "Record ID" +#~ msgstr "记录 ID" + +#~ msgid "Record Name" +#~ msgstr "记录名称" + +#~ msgid "Responsible User" +#~ msgstr "责任用户" + +#~ msgid "Review Checkpoints" +#~ msgstr "审查检查点" + +#~ msgid "Reviewed" +#~ msgstr "已审阅" + +#~ msgid "SMS Delivery error" +#~ msgstr "短信发送错误" + +#~ msgid "Set as reviewed" +#~ msgstr "设置为已读" + +#~ msgid "Status" +#~ msgstr "状态" + +#~ msgid "" +#~ "Status based on activities\n" +#~ "Overdue: Due date is already passed\n" +#~ "Today: Activity date is today\n" +#~ "Planned: Future activities." +#~ msgstr "" +#~ "基于活动的状态\n" +#~ "逾期:已经超过截止日期\n" +#~ "现今:活动日期是当天\n" +#~ "计划:未来的活动。" + +#~ msgid "" +#~ "The connectors list the new records to verify\n" +#~ " based on their type. Only some need a manual\n" +#~ " review." +#~ msgstr "" +#~ "连接器列出要验证的新记录\n" +#~ " 根据他们的类型。只有一些人需要手册\n" +#~ " 回顾。" + +#~ msgid "The record has been imported from this backend" +#~ msgstr "记录已经成功从后台导入" + +#~ msgid "The record to review." +#~ msgstr "要审查的记录。" + +#~ msgid "The selected checkpoints will be set as reviewed." +#~ msgstr "选定的检查点将设置为已审核。" + +#~ msgid "Type of the exception activity on record." +#~ msgstr "记录的异常活动的类型。" + +#~ msgid "Unread Messages" +#~ msgstr "未读消息" + +#~ msgid "Unread Messages Counter" +#~ msgstr "未读消息计数器" + +#~ msgid "" +#~ "When a connector imports new records which have\n" +#~ " configuration or reviews to do manually, they\n" +#~ " will appear in this list. Once a record has been\n" +#~ " checked, click on the 'Reviewed' button." +#~ msgstr "" +#~ "当连接器导入具有的新记录时\n" +#~ " 他们需要手动配置或评论\n" +#~ " 将出现在此列表中。一旦有记录\n" +#~ " 选中,单击“已审核”按钮。" + +#~ msgid "to verify it:" +#~ msgstr "验证它:" + +#~ msgid "If checked new messages require your attention." +#~ msgstr "如果选中,则需要您注意新消息。" + +#~ msgid "Overdue" +#~ msgstr "逾期" + +#~ msgid "Planned" +#~ msgstr "计划" + +#~ msgid "Today" +#~ msgstr "今天" + +#~ msgid "Apply" +#~ msgstr "应用" + +#~ msgid "Backends" +#~ msgstr "后台" + +#~ msgid "Configure Connector" +#~ msgstr "配置连接器" + +#~ msgid "Open Connector Menu" +#~ msgstr "打开连接器菜单" + +#~ msgid "or" +#~ msgstr "或" diff --git a/connector/models/__init__.py b/connector/models/__init__.py new file mode 100644 index 000000000..30e6777ea --- /dev/null +++ b/connector/models/__init__.py @@ -0,0 +1,2 @@ +from . import backend_model +from . import queue_job diff --git a/connector/models/backend_model.py b/connector/models/backend_model.py new file mode 100644 index 000000000..eed6c99d8 --- /dev/null +++ b/connector/models/backend_model.py @@ -0,0 +1,121 @@ +# Copyright 2013 Camptocamp SA +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html) + + +from odoo import fields, models + + +class ConnectorBackend(models.AbstractModel): + """An instance of an external backend to synchronize with. + + The backends have to ``_inherit`` this model in the connectors + modules. + + The components articulates around a collection, which in the context of the + connectors is called a Backend. + + It must be defined as a Model that inherits from ``'connector.backend'``. + + Example with the Magento Connector:: + + # in connector_magento/models/magento_backend.py + + class MagentoBackend(models.Model): + _name = 'magento.backend' + _inherit = 'connector.backend' + _description = 'Magento Backend' + + # the version in not mandatory + @api.model + def _select_versions(self): + \"\"\" Available versions + + Can be inherited to add custom versions. + \"\"\" + return [('1.7', 'Magento 1.7')] + + location = fields.Char(string='Location', required=True) + username = fields.Char(string='Username') + password = fields.Char(string='Password') + versions = fields.Selection( + selection='_select_versions', required=True + ) + + + """ + + _name = "connector.backend" + _inherit = ["collection.base"] + _description = "Connector Backend" + + +class ExternalBinding(models.AbstractModel): + """An abstract model for bindings to external records. + + An external binding is a binding between a backend and Odoo. For + example, for a partner, it could be ``magento.res.partner`` or for a + product, ``magento.product``. + + The final model, will be an ``_inherits`` of the Odoo model and + will ``_inherit`` this model. + + It will have a relation to the record (via ``_inherits``) and to the + concrete backend model (``magento.backend`` for instance). + + It will also contains all the data relative to the backend for the + record. + + It needs to implements at least these fields: + + odoo_id + The many2one to the record it links (used by ``_inherits``). + + backend_id + The many2one to the backend (for instance ``magento.backend``). + + external_id + The ID on the backend. + + sync_date + Last date of synchronization + + + The definition of the field relations is to be done in the + concrete classes because the relations themselves do not exist in + this addon. + + For example, for a ``res.partner.category`` from Magento, I would have + (this is a consolidation of all the columns from the abstract models, + in ``magentoerpconnect`` you would not find that):: + + class MagentoResPartnerCategory(models.Model): + _name = 'magento.res.partner.category' + + _inherits = {'res.partner.category': 'odoo_id'} + + odoo_id = fields.Many2one(comodel_name='res.partner.category', + string='Partner Category', + required=True, + ondelete='cascade') + backend_id = fields.Many2one( + comodel_name='magento.backend', + string='Magento Backend', + required=True, + ondelete='restrict') + external_id = fields.Char(string='ID on Magento') + tax_class_id = fields.Integer(string='Tax Class ID') + + _sql_constraints = [ + ('magento_uniq', 'unique(backend_id, magento_id)', + 'Partner Tag with same ID on Magento already exists.'), + ] + + + """ + + _name = "external.binding" + _description = "External Binding (abstract)" + + sync_date = fields.Datetime(string="Last synchronization date") + # add other fields in concrete models + # XXX we could add a default 'external_id' diff --git a/connector/models/queue_job.py b/connector/models/queue_job.py new file mode 100644 index 000000000..afdf8dba5 --- /dev/null +++ b/connector/models/queue_job.py @@ -0,0 +1,43 @@ +# Copyright 2017 Camptocamp SA +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html) + +from odoo import _, models + + +class QueueJob(models.Model): + _inherit = "queue.job" + + def related_action_unwrap_binding(self, component_usage="binder"): + """Open a form view with the unwrapped record. + + For instance, for a job on a ``magento.product.product``, + it will open a ``product.product`` form view with the unwrapped + record. + + :param component_usage: base component usage to search for the binder + """ + self.ensure_one() + model_name = self.model_name + binding = self.env[model_name].browse(self.records.ids).exists() + if not binding: + return None + if len(binding) > 1: + # not handled + return None + action = { + "name": _("Related Record"), + "type": "ir.actions.act_window", + "view_type": "form", + "view_mode": "form", + } + with binding.backend_id.work_on(binding._name) as work: + binder = work.component(usage=component_usage) + try: + model = binder.unwrap_model() + record = binder.unwrap_binding(binding) + # the unwrapped record will be displayed + action.update({"res_model": model, "res_id": record.id}) + except ValueError: + # the binding record will be displayed + action.update({"res_model": binding._name, "res_id": binding.id}) + return action diff --git a/connector/pyproject.toml b/connector/pyproject.toml new file mode 100644 index 000000000..4231d0ccc --- /dev/null +++ b/connector/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/connector/readme/CONTRIBUTORS.md b/connector/readme/CONTRIBUTORS.md new file mode 100644 index 000000000..81bf70196 --- /dev/null +++ b/connector/readme/CONTRIBUTORS.md @@ -0,0 +1,27 @@ +- Guewen Baconnier at Camptocamp +- Alexandre Fayolle at Camptocamp +- Benoit Guillot at Akretion +- Nicolas Bessi at Camptocamp +- Joël Grand-Guillaume at Camptocamp +- Arthur Vuillard at Akretion +- Sebastien Beau at Akretion +- Laurent Mignon at Acsone +- Leonardo Pistone at Camptocamp +- David Béal at Akretion +- Christophe Combelles at Anybox +- Stéphane Bidoul at Acsone +- Malte Jacobi at IBO / HTW +- Laetitia Gangloff at Acsone +- David Lefever at Taktik S.A. +- Jos de Graeve at Apertoso NV +- Jean-Sébastien Suzanne at Anybox +- Leonardo Donelli at MONK Software +- Mathias Colpaert +- Yannick Vaucher at Camptocamp +- Nicolas Piganeau at NDP Systèmes +- Florent Thomas at Mind And Go +- Matthieu Dietrich at Camptocamp +- Olivier Laurent at Acsone +- Eric Antones at NuoBiT Solutions S.L. +- Asier Neira at Factor Libre S.L. +- Nguyen Minh Chien at Trobz. diff --git a/connector/readme/CREDITS.md b/connector/readme/CREDITS.md new file mode 100644 index 000000000..83b3ec91f --- /dev/null +++ b/connector/readme/CREDITS.md @@ -0,0 +1 @@ +The migration of this module from 17.0 to 18.0 was financially supported by Camptocamp. diff --git a/connector/readme/DESCRIPTION.md b/connector/readme/DESCRIPTION.md new file mode 100644 index 000000000..280134e16 --- /dev/null +++ b/connector/readme/DESCRIPTION.md @@ -0,0 +1,41 @@ +This is a framework designed to build connectors with external systems, +usually called `Backends` in the documentation. + +Documentation: + +It features: + +- A jobs queue + + > In which the connectors can push functions (synchronization tasks) + > to be executed later. + +- An event pattern + + > The connectors can subscribe listener functions on the events, + > executed when the events are fired. + +- Connector base classes + + > Called `ConnectorUnit`. + > + > Include base classes for the use in connectors, ready to be + > extended: + > + > - `Synchronizer`: flow of an import or export + > - `Mapper`: transform a record according to mapping rules + > - `Binder`: link external IDs with local IDS + > - `BackendAdapter`: adapter interface for the exchanges with the + > backend + > - But `ConnectorUnit` can be extended to accomplish any task + +- A multi-backend support + + > Each `ConnectorUnit` can be registered amongst a backend type (eg. + > Magento) and a backend version (allow to have a different `Mapper` + > for each backend's version for instance) + +It is used for example used to connect +[Magento](http://odoo-magento-connector.com) and +[Prestashop](https://github.com/OCA/connector-prestashop), but also used +with Solr, CMIS, ... diff --git a/connector/readme/HISTORY.md b/connector/readme/HISTORY.md new file mode 100644 index 000000000..b0d14a600 --- /dev/null +++ b/connector/readme/HISTORY.md @@ -0,0 +1,5 @@ +## Next + +## 12.0.1.0.0 (2018-11-26) + +- \[MIGRATION\] from 12.0 branched at rev. 324e006 diff --git a/connector/readme/USAGE.md b/connector/readme/USAGE.md new file mode 100644 index 000000000..2475ec166 --- /dev/null +++ b/connector/readme/USAGE.md @@ -0,0 +1,3 @@ +This module does nothing on its own. It is a ground for developing +advanced connector modules. For further information, please go on: + diff --git a/connector/security/connector_security.xml b/connector/security/connector_security.xml new file mode 100644 index 000000000..63196f95e --- /dev/null +++ b/connector/security/connector_security.xml @@ -0,0 +1,15 @@ + + + + Connector + 20 + + + Connector Manager + + + + + + + diff --git a/connector/static/description/icon.png b/connector/static/description/icon.png new file mode 100644 index 000000000..4a7c781b2 Binary files /dev/null and b/connector/static/description/icon.png differ diff --git a/connector/static/description/icon.svg b/connector/static/description/icon.svg new file mode 100644 index 000000000..6cb619e0b --- /dev/null +++ b/connector/static/description/icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/connector/static/description/index.html b/connector/static/description/index.html new file mode 100644 index 000000000..d1817e2a9 --- /dev/null +++ b/connector/static/description/index.html @@ -0,0 +1,522 @@ + + + + + +Connector + + + +
+

Connector

+ + +

Beta License: LGPL-3 OCA/connector Translate me on Weblate Try me on Runboat

+

This is a framework designed to build connectors with external systems, +usually called Backends in the documentation.

+

Documentation: http://odoo-connector.com

+

It features:

+
    +
  • A jobs queue

    +
    +

    In which the connectors can push functions (synchronization tasks) +to be executed later.

    +
    +
  • +
  • An event pattern

    +
    +

    The connectors can subscribe listener functions on the events, +executed when the events are fired.

    +
    +
  • +
  • Connector base classes

    +
    +

    Called ConnectorUnit.

    +

    Include base classes for the use in connectors, ready to be +extended:

    +
      +
    • Synchronizer: flow of an import or export
    • +
    • Mapper: transform a record according to mapping rules
    • +
    • Binder: link external IDs with local IDS
    • +
    • BackendAdapter: adapter interface for the exchanges with +the backend
    • +
    • But ConnectorUnit can be extended to accomplish any task
    • +
    +
    +
  • +
  • A multi-backend support

    +
    +

    Each ConnectorUnit can be registered amongst a backend type +(eg. Magento) and a backend version (allow to have a different +Mapper for each backend’s version for instance)

    +
    +
  • +
+

It is used for example used to connect +Magento and +Prestashop, but also +used with Solr, CMIS, …

+

Table of contents

+ +
+

Usage

+

This module does nothing on its own. It is a ground for developing +advanced connector modules. For further information, please go on: +http://odoo-connector.com

+
+
+

Changelog

+ +
+

12.0.1.0.0 (2018-11-26)

+
    +
  • [MIGRATION] from 12.0 branched at rev. 324e006
  • +
+
+
+
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Camptocamp
  • +
+
+
+

Contributors

+
    +
  • Guewen Baconnier at Camptocamp
  • +
  • Alexandre Fayolle at Camptocamp
  • +
  • Benoit Guillot at Akretion
  • +
  • Nicolas Bessi at Camptocamp
  • +
  • Joël Grand-Guillaume at Camptocamp
  • +
  • Arthur Vuillard at Akretion
  • +
  • Sebastien Beau at Akretion
  • +
  • Laurent Mignon at Acsone
  • +
  • Leonardo Pistone at Camptocamp
  • +
  • David Béal at Akretion
  • +
  • Christophe Combelles at Anybox
  • +
  • Stéphane Bidoul at Acsone
  • +
  • Malte Jacobi at IBO / HTW
  • +
  • Laetitia Gangloff at Acsone
  • +
  • David Lefever at Taktik S.A.
  • +
  • Jos de Graeve at Apertoso NV
  • +
  • Jean-Sébastien Suzanne at Anybox
  • +
  • Leonardo Donelli at MONK Software
  • +
  • Mathias Colpaert
  • +
  • Yannick Vaucher at Camptocamp
  • +
  • Nicolas Piganeau at NDP Systèmes
  • +
  • Florent Thomas at Mind And Go
  • +
  • Matthieu Dietrich at Camptocamp
  • +
  • Olivier Laurent at Acsone
  • +
  • Eric Antones at NuoBiT Solutions S.L.
  • +
  • Asier Neira at Factor Libre S.L.
  • +
  • Nguyen Minh Chien at Trobz.
  • +
+
+
+

Other credits

+

The migration of this module from 17.0 to 18.0 was financially supported +by Camptocamp.

+
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

This module is part of the OCA/connector project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/connector/tests/__init__.py b/connector/tests/__init__.py new file mode 100644 index 000000000..c6dfe86f1 --- /dev/null +++ b/connector/tests/__init__.py @@ -0,0 +1,4 @@ +from . import test_advisory_lock +from . import test_listener +from . import test_locker +from . import test_mapper diff --git a/connector/tests/test_advisory_lock.py b/connector/tests/test_advisory_lock.py new file mode 100644 index 000000000..7e8556ab8 --- /dev/null +++ b/connector/tests/test_advisory_lock.py @@ -0,0 +1,67 @@ +# Copyright 2017 Camptocamp SA +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html) + +from unittest import mock + +from odoo import api +from odoo.modules.registry import Registry +from odoo.tests import common + +from odoo.addons.component.core import WorkContext +from odoo.addons.component.tests.common import TransactionComponentCase +from odoo.addons.connector.database import pg_try_advisory_lock +from odoo.addons.queue_job.exception import RetryableJobError + + +class TestAdvisoryLock(TransactionComponentCase): + def setUp(self): + super().setUp() + self.registry2 = Registry(common.get_db_name()) + self.cr2 = self.registry2.cursor() + self.env2 = api.Environment(self.cr2, self.env.uid, {}) + + @self.addCleanup + def reset_cr2(): + # rollback and close the cursor, and reset the environments + self.env2.reset() + self.cr2.rollback() + self.cr2.close() + + def test_concurrent_lock(self): + """2 concurrent transactions cannot acquire the same lock""" + # the lock is based on a string, a second transaction trying + # to acquire the same lock won't be able to acquire it + lock = "import_record({}, {}, {}, {})".format( + "backend.name", 1, "res.partner", "999999" + ) + acquired = pg_try_advisory_lock(self.env, lock) + self.assertTrue(acquired) + # we test the base function + inner_acquired = pg_try_advisory_lock(self.env2, lock) + self.assertFalse(inner_acquired) + + def test_concurrent_import_lock(self): + """A 2nd concurrent transaction must retry""" + # the lock is based on a string, a second transaction trying + # to acquire the same lock won't be able to acquire it + lock = "import_record({}, {}, {}, {})".format( + "backend.name", 1, "res.partner", "999999" + ) + + backend = mock.MagicMock() + backend.env = self.env + work = WorkContext(model_name="res.partner", collection=backend) + # we test the function through a Component instance + component = work.component_by_name("base.connector") + # acquire the lock + component.advisory_lock_or_retry(lock) + + # instanciate another component using a different odoo env + # hence another PG transaction + backend2 = mock.MagicMock() + backend2.env = self.env2 + work2 = WorkContext(model_name="res.partner", collection=backend2) + component2 = work2.component_by_name("base.connector") + with self.assertRaises(RetryableJobError) as cm: + component2.advisory_lock_or_retry(lock, retry_seconds=3) + self.assertEqual(cm.exception.seconds, 3) diff --git a/connector/tests/test_listener.py b/connector/tests/test_listener.py new file mode 100644 index 000000000..d06d52b5b --- /dev/null +++ b/connector/tests/test_listener.py @@ -0,0 +1,59 @@ +# Copyright 2017 Camptocamp SA +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html) + +from unittest import mock + +from odoo.tools import frozendict + +from odoo.addons.component.core import Component +from odoo.addons.component.tests.common import TransactionComponentRegistryCase +from odoo.addons.component_event.components.event import skip_if +from odoo.addons.component_event.core import EventWorkContext +from odoo.addons.connector import components + + +class TestEventListener(TransactionComponentRegistryCase): + """Test Connecter Listener""" + + def setUp(self): + super().setUp() + self._setup_registry(self) + + def test_skip_if_no_connector_export(self): + class MyEventListener(Component): + _name = "my.event.listener" + _inherit = "base.event.listener" + + def on_record_create(self, record, fields=None): + assert True + + class MyOtherEventListener(Component): + _name = "my.other.event.listener" + _inherit = "base.connector.listener" + + @skip_if(lambda self, record, fields=None: self.no_connector_export(record)) + def on_record_create(self, record, fields=None): + raise AssertionError() + + self.env.context = frozendict(self.env.context, no_connector_export=True) + work = EventWorkContext( + model_name="res.users", env=self.env, components_registry=self.comp_registry + ) + + # get the collecter to notify the event + # we don't mind about the collection and the model here, + # the events we test are global + self.collecter = self.comp_registry["base.event.collecter"](work) + + self._build_components( + components.core.BaseConnectorComponent, + components.listener.ConnectorListener, + MyEventListener, + MyOtherEventListener, + ) + + # collect the event and notify it + record = mock.Mock(name="record") + collected = self.collecter.collect_events("on_record_create") + self.assertEqual(2, len(collected.events)) + collected.notify(record) diff --git a/connector/tests/test_locker.py b/connector/tests/test_locker.py new file mode 100644 index 000000000..2c15eedcc --- /dev/null +++ b/connector/tests/test_locker.py @@ -0,0 +1,44 @@ +# Copyright 2018 Camptocamp SA +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +from unittest import mock + +from odoo import api +from odoo.modules.registry import Registry +from odoo.tests import common + +from odoo.addons.component.core import WorkContext +from odoo.addons.component.tests.common import TransactionComponentRegistryCase +from odoo.addons.queue_job.exception import RetryableJobError + + +class TestLocker(TransactionComponentRegistryCase): + def setUp(self): + super().setUp() + self.backend = mock.MagicMock(name="backend") + self.backend.env = self.env + + self.registry2 = Registry(common.get_db_name()) + self.cr2 = self.registry2.cursor() + self.env2 = api.Environment(self.cr2, self.env.uid, {}) + self.backend2 = mock.MagicMock(name="backend2") + self.backend2.env = self.env2 + + @self.addCleanup + def reset_cr2(): + # rollback and close the cursor, and reset the environments + self.env2.reset() + self.cr2.rollback() + self.cr2.close() + + def test_lock(self): + """Lock a record""" + main_partner = self.env.ref("base.main_partner") + work = WorkContext(model_name="res.partner", collection=self.backend) + work.component("record.locker").lock(main_partner) + + main_partner2 = self.env2.ref("base.main_partner") + work2 = WorkContext(model_name="res.partner", collection=self.backend2) + locker2 = work2.component("record.locker") + with self.assertRaises(RetryableJobError): + locker2.lock(main_partner2) diff --git a/connector/tests/test_mapper.py b/connector/tests/test_mapper.py new file mode 100644 index 000000000..98d7e611f --- /dev/null +++ b/connector/tests/test_mapper.py @@ -0,0 +1,933 @@ +# Copyright 2013 Camptocamp SA +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html) + +from unittest import mock + +from odoo.addons.component.core import Component, WorkContext +from odoo.addons.component.tests.common import TransactionComponentRegistryCase +from odoo.addons.connector.components.mapper import ( + MapOptions, + MappingDefinition, + changed_by, + convert, + external_to_m2o, + follow_m2o_relations, + m2o_to_external, + mapping, + none, + only_create, +) + + +class TestMapper(TransactionComponentRegistryCase): + def setUp(self): + super().setUp() + self._setup_registry(self) + self.comp_registry.load_components("connector") + + def test_mapping_decorator(self): + class KifKrokerMapper(Component): + _name = "kif.kroker.mapper" + _inherit = "base.mapper" + + @changed_by("name", "city") + @mapping + @only_create + def name(self): + pass + + @changed_by("email") + @mapping + def email(self): + pass + + @changed_by("street") + @mapping + def street(self): + pass + + def no_decorator(self): + pass + + # build our mapper component + KifKrokerMapper._build_component(self.comp_registry) + + # what mappings we expect + name_def = MappingDefinition(changed_by={"name", "city"}, only_create=True) + email_def = MappingDefinition(changed_by={"email"}, only_create=False) + street_def = MappingDefinition(changed_by={"street"}, only_create=False) + + # get our component by name in the components registry + comp = self.comp_registry["kif.kroker.mapper"] + # _map_methods contains the aggregated mapping methods for a Mapper + self.assertEqual( + comp._map_methods, + {"name": name_def, "email": email_def, "street": street_def}, + ) + + def test_mapping_decorator_cross_classes(self): + """Mappings should not propagate to other classes""" + + class MomMapper(Component): + _name = "mom.mapper" + _inherit = "base.mapper" + _apply_on = "res.users" + + @changed_by("name", "city") + @mapping + def name(self): + pass + + class ZappMapper(Component): + _name = "zapp.mapper" + _inherit = "base.mapper" + _apply_on = "res.users" + + @changed_by("email") + @only_create + @mapping + def email(self): + pass + + self._build_components(MomMapper, ZappMapper) + + mom_def = MappingDefinition(changed_by={"name", "city"}, only_create=False) + zapp_def = MappingDefinition(changed_by={"email"}, only_create=True) + + comp = self.comp_registry["mom.mapper"] + self.assertEqual(comp._map_methods, {"name": mom_def}) + comp = self.comp_registry["zapp.mapper"] + self.assertEqual(comp._map_methods, {"email": zapp_def}) + + def test_mapping_decorator_cumul(self): + """Mappings should cumulate the ``super`` mappings + and the local mappings.""" + + class FryMapper(Component): + _name = "fry.mapper" + _inherit = "base.mapper" + _apply_on = "res.users" + + @changed_by("name", "city") + @mapping + def name(self): + pass + + # pylint: disable=R7980 + class FryMapperInherit(Component): + _inherit = "fry.mapper" + + @changed_by("email") + @mapping + def email(self): + pass + + self._build_components(FryMapper, FryMapperInherit) + + name_def = MappingDefinition(changed_by={"name", "city"}, only_create=False) + email_def = MappingDefinition(changed_by={"email"}, only_create=False) + + comp = self.comp_registry["fry.mapper"] + self.assertEqual(comp._map_methods, {"name": name_def, "email": email_def}) + + def test_mapping_decorator_cumul_changed_by(self): + """Mappings should cumulate the changed_by fields of the + ``super`` mappings and the local mappings""" + + class FryMapper(Component): + _name = "fry.mapper" + _inherit = "base.mapper" + _apply_on = "res.users" + + @changed_by("name", "city") + @mapping + def name(self): + pass + + class FryMapperInherit(Component): + _inherit = "fry.mapper" # pylint: disable=R8180 + _apply_on = "res.users" + + @changed_by("email") + @mapping + def name(self): + pass + + class ThirdMapper(Component): + _name = "third.mapper" + _inherit = "fry.mapper" + _apply_on = "res.users" + + @changed_by("email", "street") + @mapping + def name(self): + pass + + self._build_components(FryMapper, FryMapperInherit, ThirdMapper) + + name_def = MappingDefinition( + changed_by={"name", "city", "email"}, only_create=False + ) + + comp = self.comp_registry["fry.mapper"] + self.assertEqual(comp._map_methods, {"name": name_def}) + + name_def = MappingDefinition( + changed_by={"name", "city", "email", "street"}, only_create=False + ) + comp = self.comp_registry["third.mapper"] + self.assertEqual(comp._map_methods, {"name": name_def}) + + def test_several_bases_cumul(self): + class FryMapper(Component): + _name = "fry.mapper" + _inherit = "base.mapper" + _apply_on = "res.users" + + @changed_by("name", "city") + @mapping + def name(self): + pass + + @only_create + @mapping + def street(self): + pass + + @only_create + @mapping + def zip(self): + pass + + class FarnsworthMapper(Component): + _name = "farnsworth.mapper" + _inherit = "base.mapper" + _apply_on = "res.users" + + @changed_by("email") + @mapping + def name(self): + pass + + @changed_by("street") + @mapping + def city(self): + pass + + @mapping + def zip(self): + pass + + class ThirdMapper(Component): + _name = "third.mapper" + _inherit = ["fry.mapper", "farnsworth.mapper"] + _apply_on = "res.users" + + @changed_by("email", "street") + @mapping + def name(self): + pass + + @mapping + def email(self): + pass + + self._build_components(FryMapper, FarnsworthMapper, ThirdMapper) + + name_def = MappingDefinition( + changed_by={"name", "city", "email", "street"}, only_create=False + ) + street_def = MappingDefinition(changed_by=set(), only_create=True) + city_def = MappingDefinition(changed_by={"street"}, only_create=False) + email_def = MappingDefinition(changed_by=set(), only_create=False) + zip_def = MappingDefinition(changed_by=set(), only_create=True) + + comp = self.comp_registry["third.mapper"] + self.assertEqual(comp._map_methods["name"], name_def) + self.assertEqual(comp._map_methods["street"], street_def) + self.assertEqual(comp._map_methods["city"], city_def) + self.assertEqual(comp._map_methods["email"], email_def) + self.assertEqual(comp._map_methods["zip"], zip_def) + + def test_mapping_record(self): + """Map a record and check the result""" + + class MyMapper(Component): + _name = "my.mapper" + _inherit = "base.import.mapper" + _apply_on = "res.users" + + direct = [("name", "out_name")] + + @mapping + def street(self, record): + return {"out_street": record["street"].upper()} + + self._build_components(MyMapper) + + record = {"name": "Guewen", "street": "street"} + work = mock.MagicMock(name="WorkContext()") + mapper = self.comp_registry["my.mapper"](work) + map_record = mapper.map_record(record) + expected = {"out_name": "Guewen", "out_street": "STREET"} + self.assertEqual(map_record.values(), expected) + self.assertEqual(map_record.values(for_create=True), expected) + + def test_mapping_record_on_create(self): + """Map a record and check the result for creation of record""" + + class MyMapper(Component): + _name = "my.mapper" + _inherit = "base.import.mapper" + _apply_on = "res.users" + + direct = [("name", "out_name")] + + @mapping + def street(self, record): + return {"out_street": record["street"].upper()} + + @only_create + @mapping + def city(self, record): + return {"out_city": "city"} + + self._build_components(MyMapper) + + record = {"name": "Guewen", "street": "street"} + work = mock.MagicMock(name="WorkContext()") + mapper = self.comp_registry["my.mapper"](work) + map_record = mapper.map_record(record) + expected = {"out_name": "Guewen", "out_street": "STREET"} + self.assertEqual(map_record.values(), expected) + expected = {"out_name": "Guewen", "out_street": "STREET", "out_city": "city"} + self.assertEqual(map_record.values(for_create=True), expected) + + def test_mapping_update(self): + """Force values on a map record""" + + class MyMapper(Component): + _name = "my.mapper" + _inherit = "base.import.mapper" + + direct = [("name", "out_name")] + + @mapping + def street(self, record): + return {"out_street": record["street"].upper()} + + @only_create + @mapping + def city(self, record): + return {"out_city": "city"} + + self._build_components(MyMapper) + + record = {"name": "Guewen", "street": "street"} + work = mock.MagicMock(name="WorkContext()") + mapper = self.comp_registry["my.mapper"](work) + map_record = mapper.map_record(record) + map_record.update({"test": 1}, out_city="forced") + expected = { + "out_name": "Guewen", + "out_street": "STREET", + "out_city": "forced", + "test": 1, + } + self.assertEqual(map_record.values(), expected) + expected = { + "out_name": "Guewen", + "out_street": "STREET", + "out_city": "forced", + "test": 1, + } + self.assertEqual(map_record.values(for_create=True), expected) + + # pylint: disable=W8110 + def test_finalize(self): + """Inherit finalize to modify values""" + + class MyMapper(Component): + _name = "my.mapper" + _inherit = "base.import.mapper" + + direct = [("name", "out_name")] + + def finalize(self, record, values): + result = super().finalize(record, values) + result["test"] = "abc" + return result + + self._build_components(MyMapper) + + record = {"name": "Guewen", "street": "street"} + work = mock.MagicMock(name="WorkContext()") + mapper = self.comp_registry["my.mapper"](work) + map_record = mapper.map_record(record) + expected = {"out_name": "Guewen", "test": "abc"} + self.assertEqual(map_record.values(), expected) + expected = {"out_name": "Guewen", "test": "abc"} + self.assertEqual(map_record.values(for_create=True), expected) + + def test_some_fields(self): + """Map only a selection of fields""" + + class MyMapper(Component): + _name = "my.mapper" + _inherit = "base.import.mapper" + + direct = [("name", "out_name"), ("street", "out_street")] + + @changed_by("country") + @mapping + def country(self, record): + return {"country": "country"} + + self._build_components(MyMapper) + + record = {"name": "Guewen", "street": "street", "country": "country"} + work = mock.MagicMock(name="WorkContext()") + mapper = self.comp_registry["my.mapper"](work) + map_record = mapper.map_record(record) + expected = {"out_name": "Guewen", "country": "country"} + self.assertEqual(map_record.values(fields=["name", "country"]), expected) + expected = {"out_name": "Guewen", "country": "country"} + self.assertEqual( + map_record.values(for_create=True, fields=["name", "country"]), expected + ) + + def test_mapping_modifier(self): + """Map a direct record with a modifier function""" + + def do_nothing(field): + def transform(self, record, to_attr): + return record[field] + + return transform + + class MyMapper(Component): + _name = "my.mapper" + _inherit = "base.import.mapper" + + direct = [(do_nothing("name"), "out_name")] + + self._build_components(MyMapper) + + record = {"name": "Guewen"} + work = mock.MagicMock(name="WorkContext()") + mapper = self.comp_registry["my.mapper"](work) + map_record = mapper.map_record(record) + expected = {"out_name": "Guewen"} + self.assertEqual(map_record.values(), expected) + self.assertEqual(map_record.values(for_create=True), expected) + + def test_mapping_direct_property(self): + """Map a direct record with 'direct' being a property""" + + class MyMapper(Component): + _name = "my.mapper" + _inherit = "base.import.mapper" + + @property + def direct(self): + return [("name", "out_name")] + + self._build_components(MyMapper) + + record = {"name": "Foo"} + work = mock.MagicMock(name="WorkContext()") + mapper = self.comp_registry["my.mapper"](work) + map_record = mapper.map_record(record) + expected = {"out_name": "Foo"} + self.assertEqual(map_record.values(), expected) + self.assertEqual(map_record.values(for_create=True), expected) + + def test_mapping_convert(self): + """Map a direct record with the convert modifier function""" + + class MyMapper(Component): + _name = "my.mapper" + _inherit = "base.import.mapper" + + direct = [(convert("name", int), "out_name")] + + self._build_components(MyMapper) + + record = {"name": "300"} + work = mock.MagicMock(name="WorkContext()") + mapper = self.comp_registry["my.mapper"](work) + map_record = mapper.map_record(record) + expected = {"out_name": 300} + self.assertEqual(map_record.values(), expected) + self.assertEqual(map_record.values(for_create=True), expected) + + def test_mapping_modifier_none(self): + """Pipeline of modifiers""" + + class MyMapper(Component): + _name = "my.mapper" + _inherit = "base.import.mapper" + + direct = [(none("in_f"), "out_f"), (none("in_t"), "out_t")] + + self._build_components(MyMapper) + + record = {"in_f": False, "in_t": True} + work = mock.MagicMock(name="WorkContext()") + mapper = self.comp_registry["my.mapper"](work) + map_record = mapper.map_record(record) + expected = {"out_f": None, "out_t": True} + self.assertEqual(map_record.values(), expected) + self.assertEqual(map_record.values(for_create=True), expected) + + def test_mapping_modifier_pipeline(self): + """Pipeline of modifiers""" + + class MyMapper(Component): + _name = "my.mapper" + _inherit = "base.import.mapper" + + direct = [ + (none(convert("in_f", bool)), "out_f"), + (none(convert("in_t", bool)), "out_t"), + ] + + self._build_components(MyMapper) + + record = {"in_f": 0, "in_t": 1} + work = mock.MagicMock(name="WorkContext()") + mapper = self.comp_registry["my.mapper"](work) + map_record = mapper.map_record(record) + expected = {"out_f": None, "out_t": True} + self.assertEqual(map_record.values(), expected) + self.assertEqual(map_record.values(for_create=True), expected) + + def test_modifier_import_filter_field(self): + """A direct mapping with a modifier must still be considered + from the list of fields + """ + + class MyMapper(Component): + _name = "my.mapper" + _inherit = "base.import.mapper" + + direct = [ + ("field", "field2"), + ("no_field", "no_field2"), + (convert("name", int), "out_name"), + ] + + self._build_components(MyMapper) + + record = {"name": "300", "field": "value", "no_field": "no_value"} + work = mock.MagicMock(name="WorkContext()") + mapper = self.comp_registry["my.mapper"](work) + map_record = mapper.map_record(record) + expected = {"out_name": 300, "field2": "value"} + self.assertEqual(map_record.values(fields=["field", "name"]), expected) + self.assertEqual( + map_record.values(for_create=True, fields=["field", "name"]), expected + ) + + def test_modifier_export_filter_field(self): + """A direct mapping with a modifier on an export mapping""" + + class MyMapper(Component): + _name = "my.mapper" + _inherit = "base.export.mapper" + + direct = [ + ("field", "field2"), + ("no_field", "no_field2"), + (convert("name", int), "out_name"), + ] + + self._build_components(MyMapper) + + record = {"name": "300", "field": "value", "no_field": "no_value"} + work = mock.MagicMock(name="WorkContext()") + mapper = self.comp_registry["my.mapper"](work) + map_record = mapper.map_record(record) + expected = {"out_name": 300, "field2": "value"} + self.assertEqual(map_record.values(fields=["field", "name"]), expected) + self.assertEqual( + map_record.values(for_create=True, fields=["field", "name"]), expected + ) + + def test_mapping_custom_option(self): + """Usage of custom options in mappings""" + + class MyMapper(Component): + _name = "my.mapper" + _inherit = "base.import.mapper" + + @mapping + def any(self, record): + if self.options.custom: + res = True + else: + res = False + return {"res": res} + + self._build_components(MyMapper) + + record = {} + work = mock.MagicMock(name="WorkContext()") + mapper = self.comp_registry["my.mapper"](work) + map_record = mapper.map_record(record) + expected = {"res": True} + self.assertEqual(map_record.values(custom=True), expected) + + def test_mapping_custom_option_not_defined(self): + """Usage of custom options not defined raise AttributeError""" + + class MyMapper(Component): + _name = "my.mapper" + _inherit = "base.import.mapper" + + @mapping + def any(self, record): + if self.options.custom is None: + res = True + else: + res = False + return {"res": res} + + self._build_components(MyMapper) + + record = {} + work = mock.MagicMock(name="WorkContext()") + mapper = self.comp_registry["my.mapper"](work) + map_record = mapper.map_record(record) + expected = {"res": True} + self.assertEqual(map_record.values(), expected) + + def test_map_options(self): + """Test MapOptions""" + options = MapOptions({"xyz": "abc"}, k=1) + options.l = 2 # noqa: E741 + self.assertEqual(options["xyz"], "abc") + self.assertEqual(options["k"], 1) + self.assertEqual(options["l"], 2) + self.assertEqual(options.xyz, "abc") + self.assertEqual(options.k, 1) + self.assertEqual(options.l, 2) + self.assertEqual(options["undefined"], None) + self.assertEqual(options.undefined, None) + + def test_changed_by_fields(self): + """Test attribute ``_changed_by_fields`` on Mapper.""" + + class MyMapper(Component): + _name = "my.mapper" + _inherit = "base.export.mapper" + + direct = [ + ("street", "out_street"), + (none("in_t"), "out_t"), + (none(convert("in_f", bool)), "out_f"), + ] + + @changed_by("name", "city") + @mapping + def name(self): + pass + + @changed_by("email") + @mapping + def email(self): + pass + + def no_decorator(self): + pass + + self._build_components(MyMapper) + + work = mock.MagicMock(name="WorkContext()") + mapper = self.comp_registry["my.mapper"](work) + + self.assertEqual( + mapper.changed_by_fields(), + {"street", "in_t", "in_f", "name", "city", "email"}, + ) + + +class TestMapperRecordsets(TransactionComponentRegistryCase): + """Test mapper with "real" records instead of mocks""" + + def setUp(self): + super().setUp() + self._setup_registry(self) + self.comp_registry.load_components("connector") + + backend_record = mock.Mock() + backend_record.env = self.env + self.work = WorkContext( + model_name="res.partner", + collection=backend_record, + components_registry=self.comp_registry, + ) + + def test_mapping_modifier_follow_m2o_relations(self): + """Map with the follow_m2o_relations modifier""" + + class MyMapper(Component): + _name = "my.mapper" + _inherit = "base.import.mapper" + + direct = [(follow_m2o_relations("parent_id.name"), "parent_name")] + + self._build_components(MyMapper) + + partner = self.env.ref("base.res_partner_address_4") + mapper = self.comp_registry["my.mapper"](self.work) + map_record = mapper.map_record(partner) + expected = {"parent_name": "Deco Addict"} + self.assertEqual(map_record.values(), expected) + self.assertEqual(map_record.values(for_create=True), expected) + + +class TestMapperBinding(TransactionComponentRegistryCase): + """Test Mapper with Bindings""" + + def setUp(self): + super().setUp() + self._setup_registry(self) + self.comp_registry.load_components("connector") + + backend_record = mock.Mock() + backend_record.env = self.env + backend_record._name = "my.collection" + self.work = WorkContext( + model_name="res.partner", + collection=backend_record, + components_registry=self.comp_registry, + ) + + self.country_binder = mock.MagicMock(name="country_binder") + self.country_binder.return_value = self.country_binder + self.country_binder._name = "test.binder" + self.country_binder._inherit = "base.binder" + self.country_binder.apply_on_models = ["res.country"] + self.country_binder._usage = "binder" + self.country_binder._collection = "my.collection" + self.country_binder._abstract = False + self.comp_registry["test.binder"] = self.country_binder + + def test_mapping_m2o_to_external(self): + """Map a direct record with the m2o_to_external modifier function""" + + class MyMapper(Component): + _name = "my.mapper" + _inherit = "base.import.mapper" + _apply_on = "res.partner" + + direct = [(m2o_to_external("country_id"), "country")] + + self._build_components(MyMapper) + + partner = self.env.ref("base.main_partner") + partner.write({"country_id": self.env.ref("base.ch").id}) + self.country_binder.to_external.return_value = 10 + + mapper = self.comp_registry["my.mapper"](self.work) + map_record = mapper.map_record(partner) + self.assertEqual(map_record.values(), {"country": 10}) + self.country_binder.to_external.assert_called_once_with( + partner.country_id.id, wrap=False + ) + + def test_mapping_backend_to_m2o(self): + """Map a direct record with the backend_to_m2o modifier function""" + + class MyMapper(Component): + _name = "my.mapper" + _inherit = "base.import.mapper" + _apply_on = "res.partner" + + direct = [(external_to_m2o("country"), "country_id")] + + self._build_components(MyMapper) + + record = {"country": 10} + ch = self.env.ref("base.ch") + self.country_binder.to_internal.return_value = ch + mapper = self.comp_registry["my.mapper"](self.work) + map_record = mapper.map_record(record) + self.assertEqual(map_record.values(), {"country_id": ch.id}) + self.country_binder.to_internal.assert_called_once_with(10, unwrap=False) + + def test_mapping_record_children_no_map_child(self): + """Map a record with children, using default MapChild""" + # we need these components which make the 'link' between + # the main mapper and the line mapper + + class LineMapper(Component): + _name = "line.mapper" + _inherit = "base.import.mapper" + _apply_on = "res.currency.rate" + + direct = [("name", "name")] + + @mapping + def price(self, record): + return {"rate": record["rate"] * 2} + + @only_create + @mapping + def discount(self, record): + return {"test": 0.5} + + class MyMapper(Component): + _name = "my.mapper" + _inherit = "base.import.mapper" + _apply_on = "res.currency" + + direct = [("name", "name")] + + children = [("lines", "line_ids", "res.currency.rate")] + + self._build_components(LineMapper, MyMapper) + + record = { + "name": "SO1", + "lines": [ + {"name": "2013-11-07", "rate": 10}, + {"name": "2013-11-08", "rate": 20}, + ], + } + mapper = self.comp_registry["my.mapper"](self.work) + map_record = mapper.map_record(record) + expected = { + "name": "SO1", + "line_ids": [ + (0, 0, {"name": "2013-11-07", "rate": 20}), + (0, 0, {"name": "2013-11-08", "rate": 40}), + ], + } + self.assertEqual(map_record.values(), expected) + expected = { + "name": "SO1", + "line_ids": [ + (0, 0, {"name": "2013-11-07", "rate": 20, "test": 0.5}), + (0, 0, {"name": "2013-11-08", "rate": 40, "test": 0.5}), + ], + } + self.assertEqual(map_record.values(for_create=True), expected) + + def test_mapping_record_children(self): + """Map a record with children, using defined MapChild""" + # we need these components which make the 'link' between + # the main mapper and the line mapper + + class LineMapper(Component): + _name = "line.mapper" + _inherit = "base.import.mapper" + _apply_on = "res.currency.rate" + + direct = [("name", "name")] + + @mapping + def price(self, record): + return {"rate": record["rate"] * 2} + + @only_create + @mapping + def discount(self, record): + return {"test": 0.5} + + class LineImportMapChild(Component): + _name = "line.map.child.import" + _inherit = "base.map.child.import" + _apply_on = "res.currency.rate" + + def format_items(self, items_values): + return [("ABC", values) for values in items_values] + + class MyMapper(Component): + _name = "my.mapper" + _inherit = "base.import.mapper" + _apply_on = "res.currency" + + direct = [("name", "name")] + + children = [("lines", "line_ids", "res.currency.rate")] + + self._build_components(LineMapper, LineImportMapChild, MyMapper) + + record = { + "name": "SO1", + "lines": [ + {"name": "2013-11-07", "rate": 10}, + {"name": "2013-11-08", "rate": 20}, + ], + } + mapper = self.comp_registry["my.mapper"](self.work) + map_record = mapper.map_record(record) + expected = { + "name": "SO1", + "line_ids": [ + ("ABC", {"name": "2013-11-07", "rate": 20}), + ("ABC", {"name": "2013-11-08", "rate": 40}), + ], + } + self.assertEqual(map_record.values(), expected) + expected = { + "name": "SO1", + "line_ids": [ + ("ABC", {"name": "2013-11-07", "rate": 20, "test": 0.5}), + ("ABC", {"name": "2013-11-08", "rate": 40, "test": 0.5}), + ], + } + self.assertEqual(map_record.values(for_create=True), expected) + + def test_mapping_record_children_void(self): + """Map a record with children, using defined MapChild""" + + class LineMapper(Component): + _name = "line.mapper" + _inherit = "base.import.mapper" + _apply_on = "res.currency.rate" + + @mapping + def price(self, record): + rate = record.get("rate") + if rate and rate < 40: + return {"rate": record["rate"] * 2} + + class SaleLineImportMapChild(Component): + _name = "sale.line.mapper" + _inherit = "base.map.child.import" + _apply_on = "res.currency.rate" + + def format_items(self, items_values): + return [("ABC", values) for values in items_values] + + class ObjectMapper(Component): + _name = "currency.mapper" + _inherit = "base.import.mapper" + _apply_on = "res.currency" + + direct = [("name", "name")] + + children = [("lines", "line_ids", "res.currency.rate")] + + self._build_components(ObjectMapper, SaleLineImportMapChild, LineMapper) + + # Test with an excluded child record + record = { + "name": "SO1", + "lines": [{"rate": 10}, {"rate": 20}, {"rate": 30}, {"rate": 40}], + } + mapper = self.comp_registry["currency.mapper"](self.work) + map_record = mapper.map_record(record) + + expected = { + "name": "SO1", + "line_ids": [ + ("ABC", {"rate": 20}), + ("ABC", {"rate": 40}), + ("ABC", {"rate": 60}), + ], + } + self.assertEqual(map_record.values(), expected) diff --git a/connector/views/connector_menu.xml b/connector/views/connector_menu.xml new file mode 100644 index 000000000..73045b1c7 --- /dev/null +++ b/connector/views/connector_menu.xml @@ -0,0 +1,10 @@ + + + + + diff --git a/connector/views/res_partner_views.xml b/connector/views/res_partner_views.xml new file mode 100644 index 000000000..84c7bcc93 --- /dev/null +++ b/connector/views/res_partner_views.xml @@ -0,0 +1,22 @@ + + + + res.partner.connector.form + res.partner + + + + + + + + + + + diff --git a/test_connector/README.rst b/test_connector/README.rst new file mode 100644 index 000000000..df960807b --- /dev/null +++ b/test_connector/README.rst @@ -0,0 +1,86 @@ +=============== +Connector Tests +=============== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:ead60a4870405ecbdd25fbe8f269cf789f3b028dce5d99a977ae2eb9fb5578a2 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png + :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html + :alt: License: LGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fconnector-lightgray.png?logo=github + :target: https://github.com/OCA/connector/tree/18.0/test_connector + :alt: OCA/connector +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/connector-18-0/connector-18-0-test_connector + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/connector&target_branch=18.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This addon is not meant to be used. It extends the Odoo Models in order +to run automated tests on the Connector framework + +The basic tests are integrated within the ``connector`` addon. + +**Table of contents** + +.. contents:: + :local: + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* Camptocamp + +Contributors +------------ + +- Guewen Baconnier +- Simone Orsi + +Other credits +------------- + +The migration of this module from 17.0 to 18.0 was financially supported +by Camptocamp. + +Maintainers +----------- + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/connector `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/test_connector/__init__.py b/test_connector/__init__.py new file mode 100644 index 000000000..0650744f6 --- /dev/null +++ b/test_connector/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/test_connector/__manifest__.py b/test_connector/__manifest__.py new file mode 100644 index 000000000..651154a49 --- /dev/null +++ b/test_connector/__manifest__.py @@ -0,0 +1,18 @@ +# Copyright 2017 Camptocamp SA +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html) + +{ + "name": "Connector Tests", + "summary": "Automated tests for Connector, do not install.", + "version": "18.0.1.0.0", + "author": "Camptocamp,Odoo Community Association (OCA)", + "license": "LGPL-3", + "category": "Hidden", + "depends": ["connector"], + "website": "https://github.com/OCA/connector", + "data": [ + "security/ir.model.access.csv", + "data/queue_job_function_data.xml", + ], + "installable": True, +} diff --git a/test_connector/data/queue_job_function_data.xml b/test_connector/data/queue_job_function_data.xml new file mode 100644 index 000000000..8e5f51891 --- /dev/null +++ b/test_connector/data/queue_job_function_data.xml @@ -0,0 +1,25 @@ + + + + job_related_action_unwrap + + + + + + job_related_action_unwrap + + + diff --git a/test_connector/i18n/am.po b/test_connector/i18n/am.po new file mode 100644 index 000000000..f409e81a4 --- /dev/null +++ b/test_connector/i18n/am.po @@ -0,0 +1,116 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * test_connector +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-03-10 03:36+0000\n" +"PO-Revision-Date: 2017-03-10 03:36+0000\n" +"Last-Translator: OCA Transbot , 2017\n" +"Language-Team: Amharic (https://www.transifex.com/oca/teams/23907/am/)\n" +"Language: am\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#. module: test_connector +#: model:ir.model.constraint,message:test_connector.constraint_connector_test_binding_test_binding_uniq +#: model:ir.model.constraint,message:test_connector.constraint_no_inherits_binding_test_binding_uniq +msgid "A binding already exists for this record" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__backend_id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__backend_id +msgid "Backend" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_test_backend +msgid "Backends for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_connector_test_binding +msgid "Bindings for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_no_inherits_binding +msgid "Bindings without inherit for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__create_uid +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__create_uid +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__create_uid +#: model:ir.model.fields,field_description:test_connector.field_test_backend__create_uid +msgid "Created by" +msgstr "Creado por" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__create_date +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__create_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__create_date +#: model:ir.model.fields,field_description:test_connector.field_test_backend__create_date +msgid "Created on" +msgstr "Creado en" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__display_name +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__display_name +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__display_name +#: model:ir.model.fields,field_description:test_connector.field_test_backend__display_name +msgid "Display Name" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__id +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__id +#: model:ir.model.fields,field_description:test_connector.field_test_backend__id +msgid "ID" +msgstr "ID" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__external_id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__external_id +msgid "ID on External" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__write_uid +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__write_uid +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__write_uid +#: model:ir.model.fields,field_description:test_connector.field_test_backend__write_uid +msgid "Last Updated by" +msgstr "Última actualización por" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__write_date +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__write_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__write_date +#: model:ir.model.fields,field_description:test_connector.field_test_backend__write_date +msgid "Last Updated on" +msgstr "Última actualización en" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__sync_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__sync_date +msgid "Last synchronization date" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_connector_test_record +msgid "Records for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__odoo_id +msgid "Test Record" +msgstr "" diff --git a/test_connector/i18n/ca.po b/test_connector/i18n/ca.po new file mode 100644 index 000000000..df2feb038 --- /dev/null +++ b/test_connector/i18n/ca.po @@ -0,0 +1,116 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * test_connector +# +# Translators: +# OCA Transbot , 2018 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 11.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-01-05 16:56+0000\n" +"PO-Revision-Date: 2018-01-05 16:56+0000\n" +"Last-Translator: OCA Transbot , 2018\n" +"Language-Team: Catalan (https://www.transifex.com/oca/teams/23907/ca/)\n" +"Language: ca\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: test_connector +#: model:ir.model.constraint,message:test_connector.constraint_connector_test_binding_test_binding_uniq +#: model:ir.model.constraint,message:test_connector.constraint_no_inherits_binding_test_binding_uniq +msgid "A binding already exists for this record" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__backend_id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__backend_id +msgid "Backend" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_test_backend +msgid "Backends for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_connector_test_binding +msgid "Bindings for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_no_inherits_binding +msgid "Bindings without inherit for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__create_uid +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__create_uid +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__create_uid +#: model:ir.model.fields,field_description:test_connector.field_test_backend__create_uid +msgid "Created by" +msgstr "Creat per" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__create_date +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__create_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__create_date +#: model:ir.model.fields,field_description:test_connector.field_test_backend__create_date +msgid "Created on" +msgstr "Creat a" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__display_name +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__display_name +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__display_name +#: model:ir.model.fields,field_description:test_connector.field_test_backend__display_name +msgid "Display Name" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__id +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__id +#: model:ir.model.fields,field_description:test_connector.field_test_backend__id +msgid "ID" +msgstr "ID" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__external_id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__external_id +msgid "ID on External" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__write_uid +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__write_uid +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__write_uid +#: model:ir.model.fields,field_description:test_connector.field_test_backend__write_uid +msgid "Last Updated by" +msgstr "Darrear modificació per" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__write_date +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__write_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__write_date +#: model:ir.model.fields,field_description:test_connector.field_test_backend__write_date +msgid "Last Updated on" +msgstr "Darrera modificació el" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__sync_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__sync_date +msgid "Last synchronization date" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_connector_test_record +msgid "Records for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__odoo_id +msgid "Test Record" +msgstr "" diff --git a/test_connector/i18n/de.po b/test_connector/i18n/de.po new file mode 100644 index 000000000..1496f99a4 --- /dev/null +++ b/test_connector/i18n/de.po @@ -0,0 +1,119 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * test_connector +# +# Translators: +# OCA Transbot , 2018 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 11.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-01-05 16:56+0000\n" +"PO-Revision-Date: 2018-01-05 16:56+0000\n" +"Last-Translator: OCA Transbot , 2018\n" +"Language-Team: German (https://www.transifex.com/oca/teams/23907/de/)\n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: test_connector +#: model:ir.model.constraint,message:test_connector.constraint_connector_test_binding_test_binding_uniq +#: model:ir.model.constraint,message:test_connector.constraint_no_inherits_binding_test_binding_uniq +msgid "A binding already exists for this record" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__backend_id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__backend_id +msgid "Backend" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_test_backend +msgid "Backends for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_connector_test_binding +msgid "Bindings for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_no_inherits_binding +msgid "Bindings without inherit for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__create_uid +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__create_uid +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__create_uid +#: model:ir.model.fields,field_description:test_connector.field_test_backend__create_uid +msgid "Created by" +msgstr "Angelegt durch" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__create_date +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__create_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__create_date +#: model:ir.model.fields,field_description:test_connector.field_test_backend__create_date +msgid "Created on" +msgstr "Angelegt am" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__display_name +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__display_name +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__display_name +#: model:ir.model.fields,field_description:test_connector.field_test_backend__display_name +msgid "Display Name" +msgstr "Anzeigebezeichnung" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__id +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__id +#: model:ir.model.fields,field_description:test_connector.field_test_backend__id +msgid "ID" +msgstr "ID" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__external_id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__external_id +msgid "ID on External" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__write_uid +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__write_uid +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__write_uid +#: model:ir.model.fields,field_description:test_connector.field_test_backend__write_uid +msgid "Last Updated by" +msgstr "Zuletzt aktualisiert durch" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__write_date +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__write_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__write_date +#: model:ir.model.fields,field_description:test_connector.field_test_backend__write_date +msgid "Last Updated on" +msgstr "Zuletzt aktualisiert am" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__sync_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__sync_date +msgid "Last synchronization date" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_connector_test_record +msgid "Records for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__odoo_id +msgid "Test Record" +msgstr "" + +#~ msgid "Last Modified on" +#~ msgstr "Zuletzt aktualisiert am" diff --git a/test_connector/i18n/el_GR.po b/test_connector/i18n/el_GR.po new file mode 100644 index 000000000..211414b3d --- /dev/null +++ b/test_connector/i18n/el_GR.po @@ -0,0 +1,117 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * test_connector +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-03-10 03:36+0000\n" +"PO-Revision-Date: 2017-03-10 03:36+0000\n" +"Last-Translator: OCA Transbot , 2017\n" +"Language-Team: Greek (Greece) (https://www.transifex.com/oca/teams/23907/" +"el_GR/)\n" +"Language: el_GR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: test_connector +#: model:ir.model.constraint,message:test_connector.constraint_connector_test_binding_test_binding_uniq +#: model:ir.model.constraint,message:test_connector.constraint_no_inherits_binding_test_binding_uniq +msgid "A binding already exists for this record" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__backend_id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__backend_id +msgid "Backend" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_test_backend +msgid "Backends for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_connector_test_binding +msgid "Bindings for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_no_inherits_binding +msgid "Bindings without inherit for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__create_uid +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__create_uid +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__create_uid +#: model:ir.model.fields,field_description:test_connector.field_test_backend__create_uid +msgid "Created by" +msgstr "Δημιουργήθηκε από " + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__create_date +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__create_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__create_date +#: model:ir.model.fields,field_description:test_connector.field_test_backend__create_date +msgid "Created on" +msgstr "Δημιουργήθηκε στις" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__display_name +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__display_name +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__display_name +#: model:ir.model.fields,field_description:test_connector.field_test_backend__display_name +msgid "Display Name" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__id +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__id +#: model:ir.model.fields,field_description:test_connector.field_test_backend__id +msgid "ID" +msgstr "Κωδικός" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__external_id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__external_id +msgid "ID on External" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__write_uid +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__write_uid +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__write_uid +#: model:ir.model.fields,field_description:test_connector.field_test_backend__write_uid +msgid "Last Updated by" +msgstr "Τελευταία ενημέρωση από" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__write_date +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__write_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__write_date +#: model:ir.model.fields,field_description:test_connector.field_test_backend__write_date +msgid "Last Updated on" +msgstr "Τελευταία ενημέρωση στις" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__sync_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__sync_date +msgid "Last synchronization date" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_connector_test_record +msgid "Records for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__odoo_id +msgid "Test Record" +msgstr "" diff --git a/test_connector/i18n/es.po b/test_connector/i18n/es.po new file mode 100644 index 000000000..445c1a100 --- /dev/null +++ b/test_connector/i18n/es.po @@ -0,0 +1,120 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * test_connector +# +# Translators: +# OCA Transbot , 2018 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 11.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-01-05 16:56+0000\n" +"PO-Revision-Date: 2023-08-02 13:09+0000\n" +"Last-Translator: Ivorra78 \n" +"Language-Team: Spanish (https://www.transifex.com/oca/teams/23907/es/)\n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.17\n" + +#. module: test_connector +#: model:ir.model.constraint,message:test_connector.constraint_connector_test_binding_test_binding_uniq +#: model:ir.model.constraint,message:test_connector.constraint_no_inherits_binding_test_binding_uniq +msgid "A binding already exists for this record" +msgstr "Ya existe una vinculación para este registro" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__backend_id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__backend_id +msgid "Backend" +msgstr "Servidor" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_test_backend +msgid "Backends for testing Connector" +msgstr "Servidores para probar Conector" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_connector_test_binding +msgid "Bindings for testing Connector" +msgstr "Enlaces para las pruebas del Conector" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_no_inherits_binding +msgid "Bindings without inherit for testing Connector" +msgstr "Enlaces sin legado para las pruebas del Conector" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__create_uid +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__create_uid +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__create_uid +#: model:ir.model.fields,field_description:test_connector.field_test_backend__create_uid +msgid "Created by" +msgstr "Creado por" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__create_date +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__create_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__create_date +#: model:ir.model.fields,field_description:test_connector.field_test_backend__create_date +msgid "Created on" +msgstr "Creado en" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__display_name +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__display_name +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__display_name +#: model:ir.model.fields,field_description:test_connector.field_test_backend__display_name +msgid "Display Name" +msgstr "Nombre mostrado" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__id +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__id +#: model:ir.model.fields,field_description:test_connector.field_test_backend__id +msgid "ID" +msgstr "ID" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__external_id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__external_id +msgid "ID on External" +msgstr "ID en externo" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__write_uid +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__write_uid +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__write_uid +#: model:ir.model.fields,field_description:test_connector.field_test_backend__write_uid +msgid "Last Updated by" +msgstr "Última actualización por" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__write_date +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__write_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__write_date +#: model:ir.model.fields,field_description:test_connector.field_test_backend__write_date +msgid "Last Updated on" +msgstr "Última actualización el" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__sync_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__sync_date +msgid "Last synchronization date" +msgstr "Fecha de la última sincronización" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_connector_test_record +msgid "Records for testing Connector" +msgstr "Registros para las pruebas del Conector" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__odoo_id +msgid "Test Record" +msgstr "Registro de la prueba" + +#~ msgid "Last Modified on" +#~ msgstr "Última modificación el" diff --git a/test_connector/i18n/es_ES.po b/test_connector/i18n/es_ES.po new file mode 100644 index 000000000..ac8df8472 --- /dev/null +++ b/test_connector/i18n/es_ES.po @@ -0,0 +1,117 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * test_connector +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-03-10 03:36+0000\n" +"PO-Revision-Date: 2017-03-10 03:36+0000\n" +"Last-Translator: OCA Transbot , 2017\n" +"Language-Team: Spanish (Spain) (https://www.transifex.com/oca/teams/23907/" +"es_ES/)\n" +"Language: es_ES\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: test_connector +#: model:ir.model.constraint,message:test_connector.constraint_connector_test_binding_test_binding_uniq +#: model:ir.model.constraint,message:test_connector.constraint_no_inherits_binding_test_binding_uniq +msgid "A binding already exists for this record" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__backend_id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__backend_id +msgid "Backend" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_test_backend +msgid "Backends for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_connector_test_binding +msgid "Bindings for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_no_inherits_binding +msgid "Bindings without inherit for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__create_uid +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__create_uid +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__create_uid +#: model:ir.model.fields,field_description:test_connector.field_test_backend__create_uid +msgid "Created by" +msgstr "Creado por" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__create_date +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__create_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__create_date +#: model:ir.model.fields,field_description:test_connector.field_test_backend__create_date +msgid "Created on" +msgstr "Creado en" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__display_name +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__display_name +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__display_name +#: model:ir.model.fields,field_description:test_connector.field_test_backend__display_name +msgid "Display Name" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__id +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__id +#: model:ir.model.fields,field_description:test_connector.field_test_backend__id +msgid "ID" +msgstr "ID" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__external_id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__external_id +msgid "ID on External" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__write_uid +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__write_uid +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__write_uid +#: model:ir.model.fields,field_description:test_connector.field_test_backend__write_uid +msgid "Last Updated by" +msgstr "Última actualización por" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__write_date +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__write_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__write_date +#: model:ir.model.fields,field_description:test_connector.field_test_backend__write_date +msgid "Last Updated on" +msgstr "Última actualización en" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__sync_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__sync_date +msgid "Last synchronization date" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_connector_test_record +msgid "Records for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__odoo_id +msgid "Test Record" +msgstr "" diff --git a/test_connector/i18n/fi.po b/test_connector/i18n/fi.po new file mode 100644 index 000000000..a1900e84f --- /dev/null +++ b/test_connector/i18n/fi.po @@ -0,0 +1,119 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * test_connector +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-03-10 03:36+0000\n" +"PO-Revision-Date: 2017-03-10 03:36+0000\n" +"Last-Translator: OCA Transbot , 2017\n" +"Language-Team: Finnish (https://www.transifex.com/oca/teams/23907/fi/)\n" +"Language: fi\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: test_connector +#: model:ir.model.constraint,message:test_connector.constraint_connector_test_binding_test_binding_uniq +#: model:ir.model.constraint,message:test_connector.constraint_no_inherits_binding_test_binding_uniq +msgid "A binding already exists for this record" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__backend_id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__backend_id +msgid "Backend" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_test_backend +msgid "Backends for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_connector_test_binding +msgid "Bindings for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_no_inherits_binding +msgid "Bindings without inherit for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__create_uid +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__create_uid +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__create_uid +#: model:ir.model.fields,field_description:test_connector.field_test_backend__create_uid +msgid "Created by" +msgstr "Luonut" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__create_date +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__create_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__create_date +#: model:ir.model.fields,field_description:test_connector.field_test_backend__create_date +msgid "Created on" +msgstr "Luotu" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__display_name +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__display_name +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__display_name +#: model:ir.model.fields,field_description:test_connector.field_test_backend__display_name +msgid "Display Name" +msgstr "Nimi" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__id +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__id +#: model:ir.model.fields,field_description:test_connector.field_test_backend__id +msgid "ID" +msgstr "ID" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__external_id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__external_id +msgid "ID on External" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__write_uid +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__write_uid +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__write_uid +#: model:ir.model.fields,field_description:test_connector.field_test_backend__write_uid +msgid "Last Updated by" +msgstr "Viimeksi päivittänyt" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__write_date +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__write_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__write_date +#: model:ir.model.fields,field_description:test_connector.field_test_backend__write_date +msgid "Last Updated on" +msgstr "Viimeksi päivitetty" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__sync_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__sync_date +msgid "Last synchronization date" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_connector_test_record +msgid "Records for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__odoo_id +msgid "Test Record" +msgstr "" + +#~ msgid "Last Modified on" +#~ msgstr "Viimeksi muokattu" diff --git a/test_connector/i18n/fr.po b/test_connector/i18n/fr.po new file mode 100644 index 000000000..b1f1e54b8 --- /dev/null +++ b/test_connector/i18n/fr.po @@ -0,0 +1,132 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * test_connector +# +# Translators: +# OCA Transbot , 2018 +# Nicolas JEUDY , 2018 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 11.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-02-01 01:48+0000\n" +"PO-Revision-Date: 2018-02-01 01:48+0000\n" +"Last-Translator: Nicolas JEUDY , 2018\n" +"Language-Team: French (https://www.transifex.com/oca/teams/23907/fr/)\n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#. module: test_connector +#: model:ir.model.constraint,message:test_connector.constraint_connector_test_binding_test_binding_uniq +#: model:ir.model.constraint,message:test_connector.constraint_no_inherits_binding_test_binding_uniq +msgid "A binding already exists for this record" +msgstr "Une relation existe déjà pour cet enregistrement" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__backend_id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__backend_id +msgid "Backend" +msgstr "Backend" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_test_backend +msgid "Backends for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_connector_test_binding +msgid "Bindings for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_no_inherits_binding +msgid "Bindings without inherit for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__create_uid +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__create_uid +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__create_uid +#: model:ir.model.fields,field_description:test_connector.field_test_backend__create_uid +msgid "Created by" +msgstr "Créé par" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__create_date +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__create_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__create_date +#: model:ir.model.fields,field_description:test_connector.field_test_backend__create_date +msgid "Created on" +msgstr "Créé le" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__display_name +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__display_name +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__display_name +#: model:ir.model.fields,field_description:test_connector.field_test_backend__display_name +msgid "Display Name" +msgstr "Nom affiché" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__id +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__id +#: model:ir.model.fields,field_description:test_connector.field_test_backend__id +msgid "ID" +msgstr "ID" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__external_id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__external_id +msgid "ID on External" +msgstr "ID externe" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__write_uid +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__write_uid +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__write_uid +#: model:ir.model.fields,field_description:test_connector.field_test_backend__write_uid +msgid "Last Updated by" +msgstr "Dernière mise à jour par" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__write_date +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__write_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__write_date +#: model:ir.model.fields,field_description:test_connector.field_test_backend__write_date +msgid "Last Updated on" +msgstr "Dernière mise à jour le" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__sync_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__sync_date +msgid "Last synchronization date" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_connector_test_record +msgid "Records for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__odoo_id +msgid "Test Record" +msgstr "Enregistrement de test" + +#~ msgid "Last Modified on" +#~ msgstr "Dernière modification le" + +#~ msgid "connector.test.binding" +#~ msgstr "connector.test.binding" + +#~ msgid "connector.test.record" +#~ msgstr "connector.test.record" + +#~ msgid "no.inherits.binding" +#~ msgstr "no.inherits.binding" + +#~ msgid "test.backend" +#~ msgstr "test.backend" diff --git a/test_connector/i18n/gl.po b/test_connector/i18n/gl.po new file mode 100644 index 000000000..185bb5f82 --- /dev/null +++ b/test_connector/i18n/gl.po @@ -0,0 +1,116 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * test_connector +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-03-10 03:36+0000\n" +"PO-Revision-Date: 2017-03-10 03:36+0000\n" +"Last-Translator: OCA Transbot , 2017\n" +"Language-Team: Galician (https://www.transifex.com/oca/teams/23907/gl/)\n" +"Language: gl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: test_connector +#: model:ir.model.constraint,message:test_connector.constraint_connector_test_binding_test_binding_uniq +#: model:ir.model.constraint,message:test_connector.constraint_no_inherits_binding_test_binding_uniq +msgid "A binding already exists for this record" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__backend_id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__backend_id +msgid "Backend" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_test_backend +msgid "Backends for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_connector_test_binding +msgid "Bindings for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_no_inherits_binding +msgid "Bindings without inherit for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__create_uid +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__create_uid +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__create_uid +#: model:ir.model.fields,field_description:test_connector.field_test_backend__create_uid +msgid "Created by" +msgstr "Creado por" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__create_date +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__create_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__create_date +#: model:ir.model.fields,field_description:test_connector.field_test_backend__create_date +msgid "Created on" +msgstr "Creado en" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__display_name +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__display_name +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__display_name +#: model:ir.model.fields,field_description:test_connector.field_test_backend__display_name +msgid "Display Name" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__id +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__id +#: model:ir.model.fields,field_description:test_connector.field_test_backend__id +msgid "ID" +msgstr "ID" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__external_id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__external_id +msgid "ID on External" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__write_uid +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__write_uid +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__write_uid +#: model:ir.model.fields,field_description:test_connector.field_test_backend__write_uid +msgid "Last Updated by" +msgstr "ültima actualización por" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__write_date +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__write_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__write_date +#: model:ir.model.fields,field_description:test_connector.field_test_backend__write_date +msgid "Last Updated on" +msgstr "Última actualización en" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__sync_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__sync_date +msgid "Last synchronization date" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_connector_test_record +msgid "Records for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__odoo_id +msgid "Test Record" +msgstr "" diff --git a/test_connector/i18n/hu.po b/test_connector/i18n/hu.po new file mode 100644 index 000000000..30fd895c8 --- /dev/null +++ b/test_connector/i18n/hu.po @@ -0,0 +1,119 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * test_connector +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-03-10 03:36+0000\n" +"PO-Revision-Date: 2017-03-10 03:36+0000\n" +"Last-Translator: OCA Transbot , 2017\n" +"Language-Team: Hungarian (https://www.transifex.com/oca/teams/23907/hu/)\n" +"Language: hu\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: test_connector +#: model:ir.model.constraint,message:test_connector.constraint_connector_test_binding_test_binding_uniq +#: model:ir.model.constraint,message:test_connector.constraint_no_inherits_binding_test_binding_uniq +msgid "A binding already exists for this record" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__backend_id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__backend_id +msgid "Backend" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_test_backend +msgid "Backends for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_connector_test_binding +msgid "Bindings for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_no_inherits_binding +msgid "Bindings without inherit for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__create_uid +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__create_uid +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__create_uid +#: model:ir.model.fields,field_description:test_connector.field_test_backend__create_uid +msgid "Created by" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__create_date +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__create_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__create_date +#: model:ir.model.fields,field_description:test_connector.field_test_backend__create_date +msgid "Created on" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__display_name +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__display_name +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__display_name +#: model:ir.model.fields,field_description:test_connector.field_test_backend__display_name +msgid "Display Name" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__id +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__id +#: model:ir.model.fields,field_description:test_connector.field_test_backend__id +msgid "ID" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__external_id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__external_id +msgid "ID on External" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__write_uid +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__write_uid +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__write_uid +#: model:ir.model.fields,field_description:test_connector.field_test_backend__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__write_date +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__write_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__write_date +#: model:ir.model.fields,field_description:test_connector.field_test_backend__write_date +msgid "Last Updated on" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__sync_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__sync_date +msgid "Last synchronization date" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_connector_test_record +msgid "Records for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__odoo_id +msgid "Test Record" +msgstr "" + +#~ msgid "Version" +#~ msgstr "Verzió" diff --git a/test_connector/i18n/it.po b/test_connector/i18n/it.po new file mode 100644 index 000000000..9dec2ffa9 --- /dev/null +++ b/test_connector/i18n/it.po @@ -0,0 +1,120 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * test_connector +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-03-10 03:36+0000\n" +"PO-Revision-Date: 2024-02-06 09:36+0000\n" +"Last-Translator: mymage \n" +"Language-Team: Italian (https://www.transifex.com/oca/teams/23907/it/)\n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.17\n" + +#. module: test_connector +#: model:ir.model.constraint,message:test_connector.constraint_connector_test_binding_test_binding_uniq +#: model:ir.model.constraint,message:test_connector.constraint_no_inherits_binding_test_binding_uniq +msgid "A binding already exists for this record" +msgstr "Esiste già un collegamento per questo record" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__backend_id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__backend_id +msgid "Backend" +msgstr "Backend" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_test_backend +msgid "Backends for testing Connector" +msgstr "Backend per testare connettore" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_connector_test_binding +msgid "Bindings for testing Connector" +msgstr "Collegamenti per testare connettore" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_no_inherits_binding +msgid "Bindings without inherit for testing Connector" +msgstr "Colegamenti senza eredità per testare connettore" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__create_uid +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__create_uid +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__create_uid +#: model:ir.model.fields,field_description:test_connector.field_test_backend__create_uid +msgid "Created by" +msgstr "Creato da" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__create_date +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__create_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__create_date +#: model:ir.model.fields,field_description:test_connector.field_test_backend__create_date +msgid "Created on" +msgstr "Creato il" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__display_name +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__display_name +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__display_name +#: model:ir.model.fields,field_description:test_connector.field_test_backend__display_name +msgid "Display Name" +msgstr "Nome visualizzato" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__id +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__id +#: model:ir.model.fields,field_description:test_connector.field_test_backend__id +msgid "ID" +msgstr "ID" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__external_id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__external_id +msgid "ID on External" +msgstr "ID su esterno" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__write_uid +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__write_uid +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__write_uid +#: model:ir.model.fields,field_description:test_connector.field_test_backend__write_uid +msgid "Last Updated by" +msgstr "Ultimo aggiornamento di" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__write_date +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__write_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__write_date +#: model:ir.model.fields,field_description:test_connector.field_test_backend__write_date +msgid "Last Updated on" +msgstr "Ultimo aggiornamento il" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__sync_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__sync_date +msgid "Last synchronization date" +msgstr "Data ultima sincronizzazione" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_connector_test_record +msgid "Records for testing Connector" +msgstr "Record per testare connettore" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__odoo_id +msgid "Test Record" +msgstr "Testa record" + +#~ msgid "Last Modified on" +#~ msgstr "Ultima modifica il" diff --git a/test_connector/i18n/nl.po b/test_connector/i18n/nl.po new file mode 100644 index 000000000..e4332607d --- /dev/null +++ b/test_connector/i18n/nl.po @@ -0,0 +1,119 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * test_connector +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-03-10 03:36+0000\n" +"PO-Revision-Date: 2017-03-10 03:36+0000\n" +"Last-Translator: OCA Transbot , 2017\n" +"Language-Team: Dutch (https://www.transifex.com/oca/teams/23907/nl/)\n" +"Language: nl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: test_connector +#: model:ir.model.constraint,message:test_connector.constraint_connector_test_binding_test_binding_uniq +#: model:ir.model.constraint,message:test_connector.constraint_no_inherits_binding_test_binding_uniq +msgid "A binding already exists for this record" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__backend_id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__backend_id +msgid "Backend" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_test_backend +msgid "Backends for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_connector_test_binding +msgid "Bindings for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_no_inherits_binding +msgid "Bindings without inherit for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__create_uid +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__create_uid +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__create_uid +#: model:ir.model.fields,field_description:test_connector.field_test_backend__create_uid +msgid "Created by" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__create_date +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__create_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__create_date +#: model:ir.model.fields,field_description:test_connector.field_test_backend__create_date +msgid "Created on" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__display_name +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__display_name +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__display_name +#: model:ir.model.fields,field_description:test_connector.field_test_backend__display_name +msgid "Display Name" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__id +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__id +#: model:ir.model.fields,field_description:test_connector.field_test_backend__id +msgid "ID" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__external_id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__external_id +msgid "ID on External" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__write_uid +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__write_uid +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__write_uid +#: model:ir.model.fields,field_description:test_connector.field_test_backend__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__write_date +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__write_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__write_date +#: model:ir.model.fields,field_description:test_connector.field_test_backend__write_date +msgid "Last Updated on" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__sync_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__sync_date +msgid "Last synchronization date" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_connector_test_record +msgid "Records for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__odoo_id +msgid "Test Record" +msgstr "" + +#~ msgid "Version" +#~ msgstr "Versie" diff --git a/test_connector/i18n/pt.po b/test_connector/i18n/pt.po new file mode 100644 index 000000000..9dba8d8a4 --- /dev/null +++ b/test_connector/i18n/pt.po @@ -0,0 +1,116 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * test_connector +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-03-10 03:36+0000\n" +"PO-Revision-Date: 2017-03-10 03:36+0000\n" +"Last-Translator: OCA Transbot , 2017\n" +"Language-Team: Portuguese (https://www.transifex.com/oca/teams/23907/pt/)\n" +"Language: pt\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: test_connector +#: model:ir.model.constraint,message:test_connector.constraint_connector_test_binding_test_binding_uniq +#: model:ir.model.constraint,message:test_connector.constraint_no_inherits_binding_test_binding_uniq +msgid "A binding already exists for this record" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__backend_id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__backend_id +msgid "Backend" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_test_backend +msgid "Backends for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_connector_test_binding +msgid "Bindings for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_no_inherits_binding +msgid "Bindings without inherit for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__create_uid +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__create_uid +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__create_uid +#: model:ir.model.fields,field_description:test_connector.field_test_backend__create_uid +msgid "Created by" +msgstr "Criado por" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__create_date +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__create_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__create_date +#: model:ir.model.fields,field_description:test_connector.field_test_backend__create_date +msgid "Created on" +msgstr "Criado em" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__display_name +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__display_name +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__display_name +#: model:ir.model.fields,field_description:test_connector.field_test_backend__display_name +msgid "Display Name" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__id +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__id +#: model:ir.model.fields,field_description:test_connector.field_test_backend__id +msgid "ID" +msgstr "ID" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__external_id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__external_id +msgid "ID on External" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__write_uid +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__write_uid +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__write_uid +#: model:ir.model.fields,field_description:test_connector.field_test_backend__write_uid +msgid "Last Updated by" +msgstr "Atualizado pela última vez por" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__write_date +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__write_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__write_date +#: model:ir.model.fields,field_description:test_connector.field_test_backend__write_date +msgid "Last Updated on" +msgstr "Atualizado pela última vez em" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__sync_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__sync_date +msgid "Last synchronization date" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_connector_test_record +msgid "Records for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__odoo_id +msgid "Test Record" +msgstr "" diff --git a/test_connector/i18n/pt_BR.po b/test_connector/i18n/pt_BR.po new file mode 100644 index 000000000..dd25f5aef --- /dev/null +++ b/test_connector/i18n/pt_BR.po @@ -0,0 +1,118 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * test_connector +# +# Translators: +# OCA Transbot , 2018 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 11.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-01-05 16:56+0000\n" +"PO-Revision-Date: 2019-09-03 03:24+0000\n" +"Last-Translator: Rodrigo Macedo \n" +"Language-Team: Portuguese (Brazil) (https://www.transifex.com/oca/" +"teams/23907/pt_BR/)\n" +"Language: pt_BR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 3.8\n" + +#. module: test_connector +#: model:ir.model.constraint,message:test_connector.constraint_connector_test_binding_test_binding_uniq +#: model:ir.model.constraint,message:test_connector.constraint_no_inherits_binding_test_binding_uniq +msgid "A binding already exists for this record" +msgstr "Já existe uma ligação para este registro" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__backend_id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__backend_id +msgid "Backend" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_test_backend +msgid "Backends for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_connector_test_binding +msgid "Bindings for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_no_inherits_binding +msgid "Bindings without inherit for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__create_uid +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__create_uid +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__create_uid +#: model:ir.model.fields,field_description:test_connector.field_test_backend__create_uid +msgid "Created by" +msgstr "Criado por" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__create_date +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__create_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__create_date +#: model:ir.model.fields,field_description:test_connector.field_test_backend__create_date +msgid "Created on" +msgstr "Criado em " + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__display_name +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__display_name +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__display_name +#: model:ir.model.fields,field_description:test_connector.field_test_backend__display_name +msgid "Display Name" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__id +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__id +#: model:ir.model.fields,field_description:test_connector.field_test_backend__id +msgid "ID" +msgstr "ID" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__external_id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__external_id +msgid "ID on External" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__write_uid +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__write_uid +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__write_uid +#: model:ir.model.fields,field_description:test_connector.field_test_backend__write_uid +msgid "Last Updated by" +msgstr "Última atualização por" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__write_date +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__write_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__write_date +#: model:ir.model.fields,field_description:test_connector.field_test_backend__write_date +msgid "Last Updated on" +msgstr "Última atualização em " + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__sync_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__sync_date +msgid "Last synchronization date" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_connector_test_record +msgid "Records for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__odoo_id +msgid "Test Record" +msgstr "" diff --git a/test_connector/i18n/pt_PT.po b/test_connector/i18n/pt_PT.po new file mode 100644 index 000000000..9977db713 --- /dev/null +++ b/test_connector/i18n/pt_PT.po @@ -0,0 +1,117 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * test_connector +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-03-10 03:36+0000\n" +"PO-Revision-Date: 2017-03-10 03:36+0000\n" +"Last-Translator: OCA Transbot , 2017\n" +"Language-Team: Portuguese (Portugal) (https://www.transifex.com/oca/" +"teams/23907/pt_PT/)\n" +"Language: pt_PT\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#. module: test_connector +#: model:ir.model.constraint,message:test_connector.constraint_connector_test_binding_test_binding_uniq +#: model:ir.model.constraint,message:test_connector.constraint_no_inherits_binding_test_binding_uniq +msgid "A binding already exists for this record" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__backend_id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__backend_id +msgid "Backend" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_test_backend +msgid "Backends for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_connector_test_binding +msgid "Bindings for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_no_inherits_binding +msgid "Bindings without inherit for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__create_uid +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__create_uid +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__create_uid +#: model:ir.model.fields,field_description:test_connector.field_test_backend__create_uid +msgid "Created by" +msgstr "Criado por" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__create_date +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__create_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__create_date +#: model:ir.model.fields,field_description:test_connector.field_test_backend__create_date +msgid "Created on" +msgstr "Criado em" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__display_name +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__display_name +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__display_name +#: model:ir.model.fields,field_description:test_connector.field_test_backend__display_name +msgid "Display Name" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__id +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__id +#: model:ir.model.fields,field_description:test_connector.field_test_backend__id +msgid "ID" +msgstr "ID" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__external_id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__external_id +msgid "ID on External" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__write_uid +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__write_uid +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__write_uid +#: model:ir.model.fields,field_description:test_connector.field_test_backend__write_uid +msgid "Last Updated by" +msgstr "Atualizado pela última vez por" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__write_date +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__write_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__write_date +#: model:ir.model.fields,field_description:test_connector.field_test_backend__write_date +msgid "Last Updated on" +msgstr "Atualizado pela última vez em" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__sync_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__sync_date +msgid "Last synchronization date" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_connector_test_record +msgid "Records for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__odoo_id +msgid "Test Record" +msgstr "" diff --git a/test_connector/i18n/sl.po b/test_connector/i18n/sl.po new file mode 100644 index 000000000..584525079 --- /dev/null +++ b/test_connector/i18n/sl.po @@ -0,0 +1,121 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * test_connector +# +# Translators: +# OCA Transbot , 2018 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 11.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-01-05 16:56+0000\n" +"PO-Revision-Date: 2023-04-11 13:27+0000\n" +"Last-Translator: Matjaz Mozetic \n" +"Language-Team: Slovenian (https://www.transifex.com/oca/teams/23907/sl/)\n" +"Language: sl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=4; plural=n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n" +"%100==4 ? 2 : 3;\n" +"X-Generator: Weblate 4.14.1\n" + +#. module: test_connector +#: model:ir.model.constraint,message:test_connector.constraint_connector_test_binding_test_binding_uniq +#: model:ir.model.constraint,message:test_connector.constraint_no_inherits_binding_test_binding_uniq +msgid "A binding already exists for this record" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__backend_id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__backend_id +msgid "Backend" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_test_backend +msgid "Backends for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_connector_test_binding +msgid "Bindings for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_no_inherits_binding +msgid "Bindings without inherit for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__create_uid +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__create_uid +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__create_uid +#: model:ir.model.fields,field_description:test_connector.field_test_backend__create_uid +msgid "Created by" +msgstr "Ustvaril" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__create_date +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__create_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__create_date +#: model:ir.model.fields,field_description:test_connector.field_test_backend__create_date +msgid "Created on" +msgstr "Ustvarjeno" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__display_name +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__display_name +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__display_name +#: model:ir.model.fields,field_description:test_connector.field_test_backend__display_name +msgid "Display Name" +msgstr "Prikazani naziv" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__id +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__id +#: model:ir.model.fields,field_description:test_connector.field_test_backend__id +msgid "ID" +msgstr "ID" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__external_id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__external_id +msgid "ID on External" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__write_uid +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__write_uid +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__write_uid +#: model:ir.model.fields,field_description:test_connector.field_test_backend__write_uid +msgid "Last Updated by" +msgstr "Zadnji posodobil" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__write_date +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__write_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__write_date +#: model:ir.model.fields,field_description:test_connector.field_test_backend__write_date +msgid "Last Updated on" +msgstr "Zadnjič posodobljeno" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__sync_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__sync_date +msgid "Last synchronization date" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_connector_test_record +msgid "Records for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__odoo_id +msgid "Test Record" +msgstr "" + +#~ msgid "Last Modified on" +#~ msgstr "Zadnjič spremenjeno" diff --git a/test_connector/i18n/test_connector.pot b/test_connector/i18n/test_connector.pot new file mode 100644 index 000000000..63adda6f2 --- /dev/null +++ b/test_connector/i18n/test_connector.pot @@ -0,0 +1,111 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * test_connector +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: test_connector +#: model:ir.model.constraint,message:test_connector.constraint_connector_test_binding_test_binding_uniq +#: model:ir.model.constraint,message:test_connector.constraint_no_inherits_binding_test_binding_uniq +msgid "A binding already exists for this record" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__backend_id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__backend_id +msgid "Backend" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_test_backend +msgid "Backends for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_connector_test_binding +msgid "Bindings for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_no_inherits_binding +msgid "Bindings without inherit for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__create_uid +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__create_uid +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__create_uid +#: model:ir.model.fields,field_description:test_connector.field_test_backend__create_uid +msgid "Created by" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__create_date +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__create_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__create_date +#: model:ir.model.fields,field_description:test_connector.field_test_backend__create_date +msgid "Created on" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__display_name +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__display_name +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__display_name +#: model:ir.model.fields,field_description:test_connector.field_test_backend__display_name +msgid "Display Name" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__id +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__id +#: model:ir.model.fields,field_description:test_connector.field_test_backend__id +msgid "ID" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__external_id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__external_id +msgid "ID on External" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__write_uid +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__write_uid +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__write_uid +#: model:ir.model.fields,field_description:test_connector.field_test_backend__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__write_date +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__write_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__write_date +#: model:ir.model.fields,field_description:test_connector.field_test_backend__write_date +msgid "Last Updated on" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__sync_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__sync_date +msgid "Last synchronization date" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_connector_test_record +msgid "Records for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__odoo_id +msgid "Test Record" +msgstr "" diff --git a/test_connector/i18n/tr.po b/test_connector/i18n/tr.po new file mode 100644 index 000000000..2548c512f --- /dev/null +++ b/test_connector/i18n/tr.po @@ -0,0 +1,116 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * test_connector +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-03-10 03:36+0000\n" +"PO-Revision-Date: 2017-03-10 03:36+0000\n" +"Last-Translator: OCA Transbot , 2017\n" +"Language-Team: Turkish (https://www.transifex.com/oca/teams/23907/tr/)\n" +"Language: tr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#. module: test_connector +#: model:ir.model.constraint,message:test_connector.constraint_connector_test_binding_test_binding_uniq +#: model:ir.model.constraint,message:test_connector.constraint_no_inherits_binding_test_binding_uniq +msgid "A binding already exists for this record" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__backend_id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__backend_id +msgid "Backend" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_test_backend +msgid "Backends for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_connector_test_binding +msgid "Bindings for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_no_inherits_binding +msgid "Bindings without inherit for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__create_uid +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__create_uid +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__create_uid +#: model:ir.model.fields,field_description:test_connector.field_test_backend__create_uid +msgid "Created by" +msgstr "Oluşturan" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__create_date +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__create_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__create_date +#: model:ir.model.fields,field_description:test_connector.field_test_backend__create_date +msgid "Created on" +msgstr "Oluşturuldu" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__display_name +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__display_name +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__display_name +#: model:ir.model.fields,field_description:test_connector.field_test_backend__display_name +msgid "Display Name" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__id +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__id +#: model:ir.model.fields,field_description:test_connector.field_test_backend__id +msgid "ID" +msgstr "ID" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__external_id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__external_id +msgid "ID on External" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__write_uid +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__write_uid +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__write_uid +#: model:ir.model.fields,field_description:test_connector.field_test_backend__write_uid +msgid "Last Updated by" +msgstr "Son güncelleyen" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__write_date +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__write_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__write_date +#: model:ir.model.fields,field_description:test_connector.field_test_backend__write_date +msgid "Last Updated on" +msgstr "Son güncelleme" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__sync_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__sync_date +msgid "Last synchronization date" +msgstr "" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_connector_test_record +msgid "Records for testing Connector" +msgstr "" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__odoo_id +msgid "Test Record" +msgstr "" diff --git a/test_connector/i18n/zh_CN.po b/test_connector/i18n/zh_CN.po new file mode 100644 index 000000000..6141a1568 --- /dev/null +++ b/test_connector/i18n/zh_CN.po @@ -0,0 +1,124 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * test_connector +# +# Translators: +# OCA Transbot , 2017 +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-03-10 03:36+0000\n" +"PO-Revision-Date: 2019-09-01 06:14+0000\n" +"Last-Translator: 黎伟杰 <674416404@qq.com>\n" +"Language-Team: Chinese (China) (https://www.transifex.com/oca/teams/23907/" +"zh_CN/)\n" +"Language: zh_CN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 3.8\n" + +#. module: test_connector +#: model:ir.model.constraint,message:test_connector.constraint_connector_test_binding_test_binding_uniq +#: model:ir.model.constraint,message:test_connector.constraint_no_inherits_binding_test_binding_uniq +msgid "A binding already exists for this record" +msgstr "此记录已存在绑定" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__backend_id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__backend_id +msgid "Backend" +msgstr "后端" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_test_backend +msgid "Backends for testing Connector" +msgstr "用于测试连接器的后端" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_connector_test_binding +msgid "Bindings for testing Connector" +msgstr "用于测试连接器的绑定" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_no_inherits_binding +msgid "Bindings without inherit for testing Connector" +msgstr "没有继承的绑定用于测试连接器" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__create_uid +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__create_uid +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__create_uid +#: model:ir.model.fields,field_description:test_connector.field_test_backend__create_uid +msgid "Created by" +msgstr "创建者" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__create_date +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__create_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__create_date +#: model:ir.model.fields,field_description:test_connector.field_test_backend__create_date +msgid "Created on" +msgstr "创建时间" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__display_name +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__display_name +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__display_name +#: model:ir.model.fields,field_description:test_connector.field_test_backend__display_name +msgid "Display Name" +msgstr "显示名称" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__id +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__id +#: model:ir.model.fields,field_description:test_connector.field_test_backend__id +msgid "ID" +msgstr "ID" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__external_id +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__external_id +msgid "ID on External" +msgstr "外部ID" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__write_uid +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__write_uid +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__write_uid +#: model:ir.model.fields,field_description:test_connector.field_test_backend__write_uid +msgid "Last Updated by" +msgstr "最后更新者" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__write_date +#: model:ir.model.fields,field_description:test_connector.field_connector_test_record__write_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__write_date +#: model:ir.model.fields,field_description:test_connector.field_test_backend__write_date +msgid "Last Updated on" +msgstr "最后更新时间" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__sync_date +#: model:ir.model.fields,field_description:test_connector.field_no_inherits_binding__sync_date +msgid "Last synchronization date" +msgstr "最后同步日期" + +#. module: test_connector +#: model:ir.model,name:test_connector.model_connector_test_record +msgid "Records for testing Connector" +msgstr "测试连接器的记录" + +#. module: test_connector +#: model:ir.model.fields,field_description:test_connector.field_connector_test_binding__odoo_id +msgid "Test Record" +msgstr "测试记录" + +#~ msgid "Last Modified on" +#~ msgstr "最后修改时间" + +#~ msgid "Version" +#~ msgstr "版本" diff --git a/test_connector/models/__init__.py b/test_connector/models/__init__.py new file mode 100644 index 000000000..0f00a6730 --- /dev/null +++ b/test_connector/models/__init__.py @@ -0,0 +1,2 @@ +from . import models +from . import components diff --git a/test_connector/models/components.py b/test_connector/models/components.py new file mode 100644 index 000000000..12dd8e536 --- /dev/null +++ b/test_connector/models/components.py @@ -0,0 +1,22 @@ +# Copyright 2016 Camptocamp SA +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html) + +from odoo.addons.component.core import Component + + +class ConnectorTestBinder(Component): + _name = "connector.test.binder" + _inherit = ["base.binder"] + _apply_on = ["connector.test.binding"] + + +class NoInheritsBinder(Component): + _name = "connector.test.no.inherits.binder" + _inherit = ["base.binder"] + _apply_on = ["no.inherits.binding"] + + def unwrap_binding(self, binding): + raise ValueError("Not an inherits") + + def unwrap_model(self): + raise ValueError("Not an inherits") diff --git a/test_connector/models/models.py b/test_connector/models/models.py new file mode 100644 index 000000000..3ea00bfa8 --- /dev/null +++ b/test_connector/models/models.py @@ -0,0 +1,72 @@ +# Copyright 2016 Camptocamp SA +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html) + +from odoo import fields, models + + +class TestBackend(models.Model): + _name = "test.backend" + _inherit = ["connector.backend"] + _description = "Backends for testing Connector" + + +class ConnectorTestRecord(models.Model): + _name = "connector.test.record" + _description = "Records for testing Connector" + + +class ConnectorTestBinding(models.Model): + _name = "connector.test.binding" + _inherit = "external.binding" + _inherits = {"connector.test.record": "odoo_id"} + _description = "Bindings for testing Connector" + + backend_id = fields.Many2one( + comodel_name="test.backend", + string="Backend", + required=True, + ondelete="restrict", + ) + external_id = fields.Integer(string="ID on External") + odoo_id = fields.Many2one( + comodel_name="connector.test.record", + string="Test Record", + required=True, + index=True, + ondelete="restrict", + ) + + _sql_constraints = [ + ( + "test_binding_uniq", + "unique(backend_id, external_id)", + "A binding already exists for this record", + ) + ] + + def job_related_action_unwrap(self): + return self + + +class NoInheritsBinding(models.Model): + _name = "no.inherits.binding" + _inherit = "external.binding" + _description = "Bindings without inherit for testing Connector" + + backend_id = fields.Many2one( + comodel_name="test.backend", + string="Backend", + required=True, + ondelete="restrict", + ) + external_id = fields.Integer(string="ID on External") + _sql_constraints = [ + ( + "test_binding_uniq", + "unique(backend_id, external_id)", + "A binding already exists for this record", + ) + ] + + def job_related_action_unwrap(self): + return self diff --git a/test_connector/pyproject.toml b/test_connector/pyproject.toml new file mode 100644 index 000000000..4231d0ccc --- /dev/null +++ b/test_connector/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/test_connector/readme/CONTRIBUTORS.md b/test_connector/readme/CONTRIBUTORS.md new file mode 100644 index 000000000..d8f0e0166 --- /dev/null +++ b/test_connector/readme/CONTRIBUTORS.md @@ -0,0 +1,2 @@ +- Guewen Baconnier \<\> +- Simone Orsi \<\> diff --git a/test_connector/readme/CREDITS.md b/test_connector/readme/CREDITS.md new file mode 100644 index 000000000..83b3ec91f --- /dev/null +++ b/test_connector/readme/CREDITS.md @@ -0,0 +1 @@ +The migration of this module from 17.0 to 18.0 was financially supported by Camptocamp. diff --git a/test_connector/readme/DESCRIPTION.md b/test_connector/readme/DESCRIPTION.md new file mode 100644 index 000000000..7e4efa5b0 --- /dev/null +++ b/test_connector/readme/DESCRIPTION.md @@ -0,0 +1,4 @@ +This addon is not meant to be used. It extends the Odoo Models in order +to run automated tests on the Connector framework + +The basic tests are integrated within the `connector` addon. diff --git a/test_connector/security/ir.model.access.csv b/test_connector/security/ir.model.access.csv new file mode 100644 index 000000000..dff04e9e5 --- /dev/null +++ b/test_connector/security/ir.model.access.csv @@ -0,0 +1,5 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_test_backend,access_test_backend,model_test_backend,connector.group_connector_manager,1,1,1,1 +access_connector_test_record,access_connector_test_record,model_connector_test_record,connector.group_connector_manager,1,1,1,1 +access_connector_test_binding,access_connector_test_binding,model_connector_test_binding,connector.group_connector_manager,1,1,1,1 +access_no_inherits_binding,access_no_inherits_binding,model_no_inherits_binding,connector.group_connector_manager,1,1,1,1 diff --git a/test_connector/static/description/icon.png b/test_connector/static/description/icon.png new file mode 100644 index 000000000..3a0328b51 Binary files /dev/null and b/test_connector/static/description/icon.png differ diff --git a/test_connector/static/description/index.html b/test_connector/static/description/index.html new file mode 100644 index 000000000..ca1f60b63 --- /dev/null +++ b/test_connector/static/description/index.html @@ -0,0 +1,432 @@ + + + + + +Connector Tests + + + +
+

Connector Tests

+ + +

Beta License: LGPL-3 OCA/connector Translate me on Weblate Try me on Runboat

+

This addon is not meant to be used. It extends the Odoo Models in order +to run automated tests on the Connector framework

+

The basic tests are integrated within the connector addon.

+

Table of contents

+ +
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Camptocamp
  • +
+
+ +
+

Other credits

+

The migration of this module from 17.0 to 18.0 was financially supported +by Camptocamp.

+
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

This module is part of the OCA/connector project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/test_connector/tests/__init__.py b/test_connector/tests/__init__.py new file mode 100644 index 000000000..c9ca22b22 --- /dev/null +++ b/test_connector/tests/__init__.py @@ -0,0 +1,2 @@ +from . import test_default_binder +from . import test_related_action_binding diff --git a/test_connector/tests/test_default_binder.py b/test_connector/tests/test_default_binder.py new file mode 100644 index 000000000..fb8ab395f --- /dev/null +++ b/test_connector/tests/test_default_binder.py @@ -0,0 +1,44 @@ +# Copyright 2013-2017 Camptocamp SA +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html) + +from odoo.addons.component.tests.common import TransactionComponentCase + + +class TestDefaultBinder(TransactionComponentCase): + """Test the default binder implementation using Components""" + + def setUp(self): + super().setUp() + + # create our backend, in case of components, + # the version would not be required + self.backend_record = self.env["test.backend"].create({}) + + def test_default_binder(self): + """Small scenario with the default binder""" + # create a work context with the model we want to work with + with self.backend_record.work_on("connector.test.binding") as work: + # get our binder component (for the model in whe work context) + self.binder = work.component(usage="binder") + test_record = self.env["connector.test.record"].create({}) + test_binding = self.env["connector.test.binding"].create( + {"backend_id": self.backend_record.id, "odoo_id": test_record.id} + ) + + # bind the test binding to external id = 99 + self.binder.bind(99, test_binding) + # find the odoo binding bound to external record 99 + binding = self.binder.to_internal(99) + self.assertEqual(binding, test_binding) + # find the odoo record bound to external record 99 + record = self.binder.to_internal(99, unwrap=True) + self.assertEqual(record, test_record) + # find the external record bound to odoo binding + external_id = self.binder.to_external(test_binding) + self.assertEqual(external_id, 99) + # find the external record bound to odoo record + external_id = self.binder.to_external(test_record, wrap=True) + self.assertEqual(external_id, 99) + self.assertEqual(self.binder.unwrap_model(), "connector.test.record") + # unwrapping the binding should give the same binding + self.assertEqual(self.binder.unwrap_binding(test_binding), test_record) diff --git a/test_connector/tests/test_related_action_binding.py b/test_connector/tests/test_related_action_binding.py new file mode 100644 index 000000000..7221eb5e1 --- /dev/null +++ b/test_connector/tests/test_related_action_binding.py @@ -0,0 +1,70 @@ +# Copyright 2013-2017 Camptocamp SA +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html) + +from unittest import mock + +from odoo.exceptions import UserError + +from odoo.addons.component.tests.common import TransactionComponentCase + + +class TestRelatedActionBinding(TransactionComponentCase): + """Test Related Actions with Bindings""" + + def setUp(self): + super().setUp() + + self.backend_record = self.env["test.backend"].create({}) + + def test_unwrap_binding(self): + """Call the unwrap binding related action""" + binding = self.env["connector.test.binding"].create( + {"backend_id": self.backend_record.id, "external_id": 99} + ) + + job = binding.with_delay().job_related_action_unwrap() + db_job = job.db_record() + action = db_job.open_related_action() + expected = { + "name": mock.ANY, + "type": "ir.actions.act_window", + "view_type": "form", + "view_mode": "form", + "res_id": binding.odoo_id.id, + "res_model": "connector.test.record", + } + self.assertEqual(action, expected) + + def test_unwrap_binding_direct_binding(self): + """Call the unwrap binding related action""" + binding = self.env["no.inherits.binding"].create( + {"backend_id": self.backend_record.id, "external_id": 99} + ) + + job = binding.with_delay().job_related_action_unwrap() + db_job = job.db_record() + action = db_job.open_related_action() + expected = { + "name": mock.ANY, + "type": "ir.actions.act_window", + "view_type": "form", + "view_mode": "form", + "res_id": binding.id, + "res_model": "no.inherits.binding", + } + self.assertEqual(action, expected) + + def test_unwrap_binding_not_exists(self): + """Call the related action on the model on non-existing record""" + binding = self.env["connector.test.binding"].create( + {"backend_id": self.backend_record.id, "external_id": 99} + ) + + job = binding.with_delay().job_related_action_unwrap() + + db_job = job.db_record() + + binding.unlink() + + with self.assertRaisesRegex(UserError, "No action available for this job"): + db_job.open_related_action()