diff --git a/MANIFEST.in b/MANIFEST.in index 6cd10b511cf..70715f18bc2 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,18 +1,12 @@ -include rpminstall_sh.txt # TODO do we need this file ? include README include LICENSE include MANIFEST.in include setup.nsi include setup.cfg -#include openerp/server.cert -#include openerp/server.pkey -#include openerp/gpl.txt -include man/openerp-server.1 -include man/openerp_serverrc.5 -recursive-include pixmaps *bmp *ico *png +include setup_rpm.sh recursive-include win32 *.py *.bat -recursive-include openerp *css *csv *html *png *po *pot -recursive-include openerp *rml *rng *sql *sxw *xml *xsl *yml +recursive-include openerp *css *csv *html *png *po *pot *rml *rng *sql *sxw *xml *xsl *yml +graft install graft debian graft doc global-exclude *pyc *~ # Exclude possible garbage from previous graft. diff --git a/README b/README index 5725ce9f866..a6fe10c8ffb 100644 --- a/README +++ b/README @@ -1,17 +1,138 @@ -About OpenERP ---------------- - -OpenERP is a free Enterprise Resource Planning and Customer Relationship -Management software. It is mainly developed to meet changing needs. - -The main functional features are: CRM & SRM, analytic and financial accounting, -double-entry stock management, sales and purchases management, tasks automation, -help desk, marketing campaign, ... and vertical modules for very specific -businesses. - -Technical features include a distributed server, flexible workflows, an object -database, dynamic GUIs, customizable reports, NET-RPC and XML-RPC interfaces, ... - -For more information, please visit: -http://www.openerp.com - +About OpenERP +------------- + +OpenERP is a free Enterprise Resource Planning and Customer Relationship +Management software. It is mainly developed to meet changing needs. + +The main functional features are: CRM & SRM, analytic and financial accounting, +double-entry stock management, sales and purchases management, tasks automation, +help desk, marketing campaign, ... and vertical modules for very specific +businesses. + +Technical features include a distributed server, flexible workflows, an object +database, dynamic GUIs, customizable reports, NET-RPC and XML-RPC interfaces, ... + +For more information, please visit: +http://www.openerp.com + +OpenERP Quick Installation Guide +--------------------------------- + +This file contains a quick guide to configure and install the OpenERP server. + +Required dependencies: +--------------------- + +You need the following software installed: + + * Python 2.5 or 2.6 + * Postgresql 8.2 or above + * Psycopg2 python module + * Reportlab pdf generation library for python + * lxml python module + * pytz python module + * PyYaml python module (install with: easy_install PyYaml) + +Some dependencies are only required for specific purposes: + +for rendering workflows graphs, you need: + * graphviz + * pyparsing + +For Luxembourg localization, you also need: + * pdftk (http://www.pdflabs.com/tools/pdftk-the-pdf-toolkit/) + +for generating reports using non .jpg images, you need: + * Python Imaging Library for python + +For Debian-based distributions, the required packages can be installed with the +following command: + + #> apt-get install -y postgresql graphviz python-psycopg2 python-lxml python-tz python-imaging + +For Fedora +if they are not installed, install: +python and postgresql + +uses yum or you can recover required packages on fedora web site in "core" or "extra" repository : +postgresql-python +python-lxml +python-imaging +python-psycopg2 +python-reportlab +graphviz +You can find pyparsing at http://pyparsing.sourceforge.net/ + +1. Check that all the required dependencies are installed. + +2. Launch the program "python ./bin/openerp-server.py -r db_user -w db_password --db_host 127.0.0.1". +See the man page for more information about options. + +3. Connect to the server using the GUI client. And follow the instructions to create a new database. + +Installation Steps +------------------ + +1. Check that all the required dependencies are installed. + +2. Create a postgresql database. + +The default database name is "terp". If you want to use another name, you +will need to provide it when launching the server (by using the commandline +option --database). + +To create a postgresql database named "terp" using the following command: + $ createdb --encoding=UNICODE terp + +If it is the first time you use postgresql you might need to create a new user +to the postgres system using the following commands (where myusername is your +unix user name): + + $ su - + # su - postgres + $ createuser openerp + Shall the new user be allowed to create databases? (y/n) y + Shall the new user be allowed to create more new users? (y/n) y + CREATE USER + $ logout + # logout + +3. Launch service daemon by "service openerp-server start". + +The first time it is run, the server will initialise the database with all the default values. + +4. Connect to the server using the GUI client. + +There are two accounts by default: + * login: admin, password:admin + * login: demo, password:demo + +Some instructions to use setup.py for a user-install. +This file should/will be moved on a proper documentation place later. + + +- Possibly clean any left-over of the previous build. + > rm -rf dist openerp_server.egg-info + +- Possibly copy the addons in the server if we want them to be packaged + together: + > rsync -av --delete \ + --exclude .bzr/ \ + --exclude .bzrignore \ + --exclude /__init__.py \ + --exclude /base \ + --exclude /base_quality_interrogation.py \ + openerp/addons + +- Create the user-local directory where we want the package to be installed: + > mkdir -p /home/openerp/openerp-tmp/lib/python2.6/site-packages/ + +- Use --prefix to specify where the package is installed and include that + place in PYTHONPATH: + > PYTHONPATH=/home/openerp/openerp-tmp/lib/python2.6/site-packages/ \ + python setup.py install --prefix=/home/openerp/openerp-tmp + +- Run the main script, again specifying the PYTHONPATH: + > PYTHONPATH=/home/openerp/openerp-tmp/lib/python2.6/site-packages/ \ + /home/openerp/openerp-tmp/bin/openerp-server + diff --git a/gunicorn.conf.py b/gunicorn.conf.py new file mode 100644 index 00000000000..7b117c040f6 --- /dev/null +++ b/gunicorn.conf.py @@ -0,0 +1,17 @@ +import openerp +# Standard OpenERP XML-RPC port. +bind = '127.0.0.1:8069' +pidfile = '.gunicorn.pid' +# This is the big TODO: safely use more than a single worker. +workers = 1 +# Some application-wide initialization is needed. +on_starting = openerp.wsgi.on_starting +when_ready = openerp.wsgi.when_ready +timeout = 240 # openerp request-response cycle can be quite long + +# Setting openerp.conf.xxx will be better than setting +# openerp.tools.config['xxx'] +conf = openerp.tools.config +conf['addons_path'] = '/home/openerp/repos/addons/trunk-xmlrpc' +conf['static_http_document_root'] = '/tmp' +#conf['log_level'] = 10 # 10 is DEBUG diff --git a/doc/Changelog b/history/Changelog similarity index 100% rename from doc/Changelog rename to history/Changelog diff --git a/doc/Changelog-4.x b/history/Changelog-4.x similarity index 100% rename from doc/Changelog-4.x rename to history/Changelog-4.x diff --git a/doc/Changelog-6.x b/history/Changelog-6.x similarity index 100% rename from doc/Changelog-6.x rename to history/Changelog-6.x diff --git a/doc/INSTALL b/history/INSTALL similarity index 100% rename from doc/INSTALL rename to history/INSTALL diff --git a/doc/README.urpmi b/history/README.urpmi similarity index 100% rename from doc/README.urpmi rename to history/README.urpmi diff --git a/doc/README.userchange b/history/README.userchange similarity index 100% rename from doc/README.userchange rename to history/README.userchange diff --git a/tools/change-loglevel.sh b/history/change-loglevel.sh similarity index 100% rename from tools/change-loglevel.sh rename to history/change-loglevel.sh diff --git a/doc/tests/check_profile_l10n_all.py b/history/check_profile_l10n_all.py similarity index 100% rename from doc/tests/check_profile_l10n_all.py rename to history/check_profile_l10n_all.py diff --git a/sql/clean-model.sql b/history/clean-model.sql similarity index 100% rename from sql/clean-model.sql rename to history/clean-model.sql diff --git a/tools/gen_graph.sh b/history/gen_graph.sh similarity index 100% rename from tools/gen_graph.sh rename to history/gen_graph.sh diff --git a/tools/get-srvstats.sh b/history/get-srvstats.sh similarity index 100% rename from tools/get-srvstats.sh rename to history/get-srvstats.sh diff --git a/tools/list-services.sh b/history/list-services.sh similarity index 100% rename from tools/list-services.sh rename to history/list-services.sh diff --git a/doc/migrate/3.3.0-3.4.0/README b/history/migrate/3.3.0-3.4.0/README similarity index 100% rename from doc/migrate/3.3.0-3.4.0/README rename to history/migrate/3.3.0-3.4.0/README diff --git a/doc/migrate/3.3.0-3.4.0/post.py b/history/migrate/3.3.0-3.4.0/post.py similarity index 100% rename from doc/migrate/3.3.0-3.4.0/post.py rename to history/migrate/3.3.0-3.4.0/post.py diff --git a/doc/migrate/3.3.0-3.4.0/pre.py b/history/migrate/3.3.0-3.4.0/pre.py similarity index 100% rename from doc/migrate/3.3.0-3.4.0/pre.py rename to history/migrate/3.3.0-3.4.0/pre.py diff --git a/doc/migrate/3.4.0-4.0.0/README b/history/migrate/3.4.0-4.0.0/README similarity index 100% rename from doc/migrate/3.4.0-4.0.0/README rename to history/migrate/3.4.0-4.0.0/README diff --git a/doc/migrate/3.4.0-4.0.0/post-tiny.py b/history/migrate/3.4.0-4.0.0/post-tiny.py similarity index 100% rename from doc/migrate/3.4.0-4.0.0/post-tiny.py rename to history/migrate/3.4.0-4.0.0/post-tiny.py diff --git a/doc/migrate/3.4.0-4.0.0/post.py b/history/migrate/3.4.0-4.0.0/post.py similarity index 100% rename from doc/migrate/3.4.0-4.0.0/post.py rename to history/migrate/3.4.0-4.0.0/post.py diff --git a/doc/migrate/3.4.0-4.0.0/pre-tiny.py b/history/migrate/3.4.0-4.0.0/pre-tiny.py similarity index 100% rename from doc/migrate/3.4.0-4.0.0/pre-tiny.py rename to history/migrate/3.4.0-4.0.0/pre-tiny.py diff --git a/doc/migrate/3.4.0-4.0.0/pre.py b/history/migrate/3.4.0-4.0.0/pre.py similarity index 100% rename from doc/migrate/3.4.0-4.0.0/pre.py rename to history/migrate/3.4.0-4.0.0/pre.py diff --git a/doc/migrate/4.0.0-4.2.0/pre.py b/history/migrate/4.0.0-4.2.0/pre.py similarity index 100% rename from doc/migrate/4.0.0-4.2.0/pre.py rename to history/migrate/4.0.0-4.2.0/pre.py diff --git a/doc/migrate/4.0.0-4.2.0/tiny/README b/history/migrate/4.0.0-4.2.0/tiny/README similarity index 100% rename from doc/migrate/4.0.0-4.2.0/tiny/README rename to history/migrate/4.0.0-4.2.0/tiny/README diff --git a/doc/migrate/4.0.0-4.2.0/tiny/pre-tiny.py b/history/migrate/4.0.0-4.2.0/tiny/pre-tiny.py similarity index 100% rename from doc/migrate/4.0.0-4.2.0/tiny/pre-tiny.py rename to history/migrate/4.0.0-4.2.0/tiny/pre-tiny.py diff --git a/doc/migrate/4.2.0-4.4.0/pre.py b/history/migrate/4.2.0-4.4.0/pre.py similarity index 100% rename from doc/migrate/4.2.0-4.4.0/pre.py rename to history/migrate/4.2.0-4.4.0/pre.py diff --git a/tools/module_graph.py b/history/module_graph.py similarity index 100% rename from tools/module_graph.py rename to history/module_graph.py diff --git a/tools/xml2yml.py b/history/xml2yml.py similarity index 100% rename from tools/xml2yml.py rename to history/xml2yml.py diff --git a/pixmaps/openerp-header.bmp b/install/openerp-header.bmp similarity index 100% rename from pixmaps/openerp-header.bmp rename to install/openerp-header.bmp diff --git a/pixmaps/openerp-header.png b/install/openerp-header.png similarity index 100% rename from pixmaps/openerp-header.png rename to install/openerp-header.png diff --git a/pixmaps/openerp-icon.ico b/install/openerp-icon.ico similarity index 100% rename from pixmaps/openerp-icon.ico rename to install/openerp-icon.ico diff --git a/pixmaps/openerp-icon.png b/install/openerp-icon.png similarity index 100% rename from pixmaps/openerp-icon.png rename to install/openerp-icon.png diff --git a/man/openerp-server.1 b/install/openerp-server.1 similarity index 100% rename from man/openerp-server.1 rename to install/openerp-server.1 diff --git a/doc/openerp-server.conf b/install/openerp-server.conf similarity index 100% rename from doc/openerp-server.conf rename to install/openerp-server.conf diff --git a/doc/openerp-server.init b/install/openerp-server.init similarity index 100% rename from doc/openerp-server.init rename to install/openerp-server.init diff --git a/doc/openerp-server.logrotate b/install/openerp-server.logrotate similarity index 100% rename from doc/openerp-server.logrotate rename to install/openerp-server.logrotate diff --git a/pixmaps/openerp.ico b/install/openerp.ico similarity index 100% rename from pixmaps/openerp.ico rename to install/openerp.ico diff --git a/pixmaps/openerp.png b/install/openerp.png similarity index 100% rename from pixmaps/openerp.png rename to install/openerp.png diff --git a/man/openerp_serverrc.5 b/install/openerp_serverrc.5 similarity index 100% rename from man/openerp_serverrc.5 rename to install/openerp_serverrc.5 diff --git a/ssl-cert.cfg b/install/ssl-cert.cfg similarity index 100% rename from ssl-cert.cfg rename to install/ssl-cert.cfg diff --git a/openerp-server b/openerp-server index 9303ed68f73..52ad49104b1 100755 --- a/openerp-server +++ b/openerp-server @@ -27,7 +27,7 @@ OpenERP is an ERP+CRM program for small and medium businesses. The whole source code is distributed under the terms of the GNU Public Licence. -(c) 2003-TODAY, Fabien Pinckaers - OpenERP s.a. +(c) 2003-TODAY, Fabien Pinckaers - OpenERP SA """ import logging @@ -88,19 +88,27 @@ def setup_pid_file(): def preload_registry(dbname): """ Preload a registry, and start the cron.""" - db, pool = openerp.pooler.get_db_and_pool(dbname, update_module=config['init'] or config['update'], pooljobs=False) - pool.get('ir.cron').restart(db.dbname) + try: + db, registry = openerp.pooler.get_db_and_pool(dbname, update_module=config['init'] or config['update'], pooljobs=False) + + # jobs will start to be processed later, when openerp.cron.start_master_thread() is called by openerp.service.start_services() + registry.schedule_cron_jobs() + except Exception: + logging.exception('Failed to initialize database `%s`.', dbname) def run_test_file(dbname, test_file): """ Preload a registry, possibly run a test file, and start the cron.""" - db, pool = openerp.pooler.get_db_and_pool(dbname, update_module=config['init'] or config['update'], pooljobs=False) + try: + db, registry = openerp.pooler.get_db_and_pool(dbname, update_module=config['init'] or config['update'], pooljobs=False) + cr = db.cursor() + logger = logging.getLogger('server') + logger.info('loading test file %s', test_file) + openerp.tools.convert_yaml_import(cr, 'base', file(test_file), {}, 'test', True) + cr.rollback() + cr.close() + except Exception: + logging.exception('Failed to initialize database `%s` and run test file `%s`.', dbname, test_file) - cr = db.cursor() - logger = logging.getLogger('server') - logger.info('loading test file %s', test_file) - openerp.tools.convert_yaml_import(cr, 'base', file(test_file), {}, 'test', True) - cr.rollback() - cr.close() def export_translation(): config = openerp.tools.config @@ -136,27 +144,6 @@ def import_translation(): cr.commit() cr.close() -def start_services(): - http_server = openerp.service.http_server - netrpc_server = openerp.service.netrpc_server - - # Instantiate local services (this is a legacy design). - openerp.osv.osv.start_object_proxy() - # Export (for RPC) services. - openerp.service.web_services.start_web_services() - - # Initialize the HTTP stack. - http_server.init_servers() - http_server.init_xmlrpc() - http_server.init_static_http() - netrpc_server.init_servers() - - # Start the main cron thread. - openerp.netsvc.start_agent() - - # Start the top-level servers threads (normally HTTP, HTTPS, and NETRPC). - openerp.netsvc.Server.startAll() - # Variable keeping track of the number of calls to the signal handler defined # below. This variable is monitored by ``quit_on_signals()``. quit_signals_received = 0 @@ -208,30 +195,16 @@ def quit_on_signals(): while quit_signals_received == 0: time.sleep(60) - openerp.netsvc.Agent.quit() - openerp.netsvc.Server.quitAll() - config = openerp.tools.config if config['pidfile']: os.unlink(config['pidfile']) - logger = logging.getLogger('server') - logger.info("Initiating shutdown") - logger.info("Hit CTRL-C again or send a second signal to force the shutdown.") - logging.shutdown() - # manually join() all threads before calling sys.exit() to allow a second signal - # to trigger _force_quit() in case some non-daemon threads won't exit cleanly. - # threading.Thread.join() should not mask signals (at least in python 2.5) - for thread in threading.enumerate(): - if thread != threading.currentThread() and not thread.isDaemon(): - while thread.isAlive(): - # need a busyloop here as thread.join() masks signals - # and would present the forced shutdown - thread.join(0.05) - time.sleep(0.05) + openerp.service.stop_services() sys.exit(0) if __name__ == "__main__": + os.environ["TZ"] = "UTC" + check_root_user() openerp.tools.config.parse_config(sys.argv[1:]) check_postgres_user() @@ -257,7 +230,7 @@ if __name__ == "__main__": if not config["stop_after_init"]: # Some module register themselves when they are loaded so we need the # services to be running before loading any registry. - start_services() + openerp.service.start_services() if config['db_name']: for dbname in config['db_name'].split(','): @@ -266,6 +239,16 @@ if __name__ == "__main__": if config["stop_after_init"]: sys.exit(0) + for m in openerp.conf.server_wide_modules: + try: + __import__(m) + # Call any post_load hook. + info = openerp.modules.module.load_information_from_description_file(m) + if info['post_load']: + getattr(sys.modules[m], info['post_load'])() + except Exception: + logging.exception('Failed to load server-wide module `%s`', m) + setup_pid_file() logger = logging.getLogger('server') logger.info('OpenERP server is running, waiting for connections...') diff --git a/openerp/__init__.py b/openerp/__init__.py index b7b5fc1b533..7e723c41f9d 100644 --- a/openerp/__init__.py +++ b/openerp/__init__.py @@ -22,6 +22,8 @@ """ OpenERP core library. """ +# The hard-coded super-user id (a.k.a. administrator, or root user). +SUPERUSER_ID = 1 import addons import conf @@ -41,6 +43,7 @@ import tiny_socket import tools import wizard import workflow +import wsgi # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerp/addons/__init__.py b/openerp/addons/__init__.py index 88a0d113151..1f863eca509 100644 --- a/openerp/addons/__init__.py +++ b/openerp/addons/__init__.py @@ -22,10 +22,15 @@ """ Addons module. -This module only serves to contain OpenERP addons. For the code to -manage those addons, see openerp.modules. This module conveniently -reexports some symbols from openerp.modules. Importing them from here -is deprecated. +This module serves to contain all OpenERP addons, across all configured addons +paths. For the code to manage those addons, see openerp.modules. + +Addons are made available here (i.e. under openerp.addons) after +openerp.tools.config.parse_config() is called (so that the addons paths +are known). + +This module also conveniently reexports some symbols from openerp.modules. +Importing them from here is deprecated. """ diff --git a/openerp/addons/base/__init__.py b/openerp/addons/base/__init__.py index 847bef71f8c..16a61521fb4 100644 --- a/openerp/addons/base/__init__.py +++ b/openerp/addons/base/__init__.py @@ -24,6 +24,7 @@ import module import res import publisher_warranty import report +import test # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerp/addons/base/__openerp__.py b/openerp/addons/base/__openerp__.py index 7e5714a9375..5233cdcbfdb 100644 --- a/openerp/addons/base/__openerp__.py +++ b/openerp/addons/base/__openerp__.py @@ -93,7 +93,10 @@ 'test/test_ir_rule.yml', # <-- These tests modify/add/delete ir_rules. 'test/test_ir_values.yml', 'test/test_edi_documents.yml', - + # Commented because this takes some time. + # This must be (un)commented with the corresponding import statement + # in test/__init__.py. + # 'test/test_ir_cron.yml', # <-- These tests perform a roolback. ], 'installable': True, 'active': True, diff --git a/openerp/addons/base/base_data.xml b/openerp/addons/base/base_data.xml index febc7ff82aa..f1c1b0e8ce1 100644 --- a/openerp/addons/base/base_data.xml +++ b/openerp/addons/base/base_data.xml @@ -1006,7 +1006,7 @@ - OpenERP S.A. + Company Name @@ -1014,13 +1014,13 @@ - Fabien Pinckaers - Chaussee de Namur 40 - 1367 - Gerompont - (+32).81.81.37.00 + Company contact name + Company street, number + Company zip + Company city + +1-212-555-12345 default - + @@ -1042,19 +1042,14 @@ - OpenERP S.A. + Company Name - Free Business Solutions - Web: http://www.openerp.com - Tel: (+32).81.81.37.00 - Bank: CPH 126-2013269-07 - IBAN: BE74 1262 0132 6907 - SWIFT: CPHBBE75 - VAT: BE0477.472.701 + Company business slogan + Web: www.companyname.com - Tel: +1-212-555-12345 + IBAN: XX12 3456 7890 1234 5678 - SWIFT: SWIFTCODE - VAT: Company vat number - - - OpenERP S.A. - - Administrator @@ -1090,16 +1085,17 @@ - - VEB - Bs - 2.95 + + + VEF + Bs.F + 0.0001 4 - - 2768.45 - + + 5.864 + @@ -1603,6 +1599,7 @@ 0.01 4 ¢ + 691.3153 diff --git a/openerp/addons/base/base_update.xml b/openerp/addons/base/base_update.xml index b87c0ef4382..444c7b5189c 100644 --- a/openerp/addons/base/base_update.xml +++ b/openerp/addons/base/base_update.xml @@ -75,29 +75,29 @@ --> - res.users.form.modif + res.users.preferences.form res.users form
- + - - - - + + + + - - - + +
@@ -147,7 +147,7 @@ - + diff --git a/openerp/addons/base/i18n/cs.po b/openerp/addons/base/i18n/cs.po index b4546192649..1a20a156fe9 100644 --- a/openerp/addons/base/i18n/cs.po +++ b/openerp/addons/base/i18n/cs.po @@ -7,14 +7,14 @@ msgstr "" "Project-Id-Version: openobject-server\n" "Report-Msgid-Bugs-To: support@openerp.com\n" "POT-Creation-Date: 2011-01-11 11:14+0000\n" -"PO-Revision-Date: 2011-09-13 11:47+0000\n" +"PO-Revision-Date: 2011-09-16 16:25+0000\n" "Last-Translator: Jiří Hajda \n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-09-14 04:40+0000\n" -"X-Generator: Launchpad (build 13921)\n" +"X-Launchpad-Export-Date: 2011-09-17 04:54+0000\n" +"X-Generator: Launchpad (build 13955)\n" "X-Poedit-Language: Czech\n" #. module: base @@ -3812,7 +3812,7 @@ msgstr "" #. module: base #: view:publisher_warranty.contract.wizard:0 msgid "Please enter the serial key provided in your contract document:" -msgstr "Prosíme zadejte sériové číslo poskytnuté ve dokumentu vaší smlouvy:" +msgstr "Prosíme zadejte sériové číslo poskytnuté v dokumentu vaší smlouvy:" #. module: base #: view:workflow.activity:0 diff --git a/openerp/addons/base/i18n/da.po b/openerp/addons/base/i18n/da.po index da07b07a1e9..2fa355ab21a 100644 --- a/openerp/addons/base/i18n/da.po +++ b/openerp/addons/base/i18n/da.po @@ -8,14 +8,14 @@ msgstr "" "Project-Id-Version: openobject-addons\n" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2011-01-11 11:14+0000\n" -"PO-Revision-Date: 2010-02-07 05:09+0000\n" -"Last-Translator: Fabien (Open ERP) \n" +"PO-Revision-Date: 2011-09-24 16:40+0000\n" +"Last-Translator: John Mertens Pallesen \n" "Language-Team: Danish \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-09-01 04:40+0000\n" -"X-Generator: Launchpad (build 13827)\n" +"X-Launchpad-Export-Date: 2011-09-25 04:40+0000\n" +"X-Generator: Launchpad (build 14012)\n" #. module: base #: view:ir.filters:0 @@ -141,7 +141,7 @@ msgstr "" #: code:addons/base/res/res_user.py:507 #, python-format msgid "Warning!" -msgstr "" +msgstr "Advarsel!" #. module: base #: code:addons/base/ir/ir_model.py:304 @@ -196,7 +196,7 @@ msgstr "" #: model:ir.actions.act_window,name:base.action_res_company_tree #: model:ir.ui.menu,name:base.menu_action_res_company_tree msgid "Company's Structure" -msgstr "" +msgstr "Virksomhedens struktur" #. module: base #: selection:base.language.install,lang:0 @@ -277,7 +277,7 @@ msgstr "" #. module: base #: field:res.partner,credit_limit:0 msgid "Credit Limit" -msgstr "" +msgstr "Kreditgrænse" #. module: base #: field:ir.model.data,date_update:0 @@ -372,7 +372,7 @@ msgstr "Fransk Guyana" #. module: base #: selection:base.language.install,lang:0 msgid "Greek / Ελληνικά" -msgstr "" +msgstr "Græsk / Greek" #. module: base #: selection:base.language.install,lang:0 @@ -483,7 +483,7 @@ msgstr "" #. module: base #: view:res.config.users:0 msgid "New User" -msgstr "" +msgstr "Ny bruger" #. module: base #: view:base.language.export:0 @@ -525,7 +525,7 @@ msgstr "Eritrea" #: view:res.config:0 #: view:res.config.installer:0 msgid "description" -msgstr "" +msgstr "Beskrivelse" #. module: base #: model:ir.ui.menu,name:base.menu_base_action_rule @@ -563,7 +563,7 @@ msgstr "" #. module: base #: selection:base.language.install,lang:0 msgid "Swedish / svenska" -msgstr "" +msgstr "Svensk / Swedish" #. module: base #: model:res.country,name:base.rs @@ -601,7 +601,7 @@ msgstr "" #. module: base #: selection:base.language.install,lang:0 msgid "Albanian / Shqip" -msgstr "" +msgstr "Albanien" #. module: base #: model:ir.ui.menu,name:base.menu_crm_config_opportunity @@ -651,7 +651,7 @@ msgstr "Spanien" #. module: base #: model:ir.ui.menu,name:base.menu_translation_export msgid "Import / Export" -msgstr "" +msgstr "Import / Eksport" #. module: base #: help:ir.actions.act_window,domain:0 @@ -692,7 +692,7 @@ msgstr "Oman" #: model:ir.actions.act_window,name:base.action_payterm_form #: model:ir.model,name:base.model_res_payterm msgid "Payment term" -msgstr "" +msgstr "Betalingsbetingelse" #. module: base #: model:res.country,name:base.nu @@ -859,7 +859,7 @@ msgstr "" #: model:ir.actions.act_window,name:base.action_publisher_warranty_contract_form #: model:ir.ui.menu,name:base.menu_publisher_warranty_contract msgid "Contracts" -msgstr "" +msgstr "Kontrakter" #. module: base #: selection:base.language.install,lang:0 @@ -884,12 +884,12 @@ msgstr "Niger" #. module: base #: selection:base.language.install,lang:0 msgid "Chinese (HK)" -msgstr "" +msgstr "Kinesisk (HK)" #. module: base #: model:res.country,name:base.ba msgid "Bosnia-Herzegovina" -msgstr "" +msgstr "Bosnien-Hercegovina" #. module: base #: view:base.language.export:0 @@ -931,7 +931,7 @@ msgstr "" #. module: base #: field:base.module.import,module_name:0 msgid "Module Name" -msgstr "" +msgstr "Modulnavn" #. module: base #: model:res.country,name:base.mh @@ -990,7 +990,7 @@ msgstr "" #. module: base #: model:ir.ui.menu,name:base.menu_hr_dasboard msgid "Dashboard" -msgstr "" +msgstr "Oversigt" #. module: base #: model:ir.ui.menu,name:base.menu_purchase_root @@ -1011,7 +1011,7 @@ msgstr "Funktioner" #: view:ir.module.module:0 #: report:ir.module.reference.graph:0 msgid "Version" -msgstr "" +msgstr "Version" #. module: base #: view:ir.model.access:0 @@ -1382,7 +1382,7 @@ msgstr "" #. module: base #: model:res.country,name:base.fi msgid "Finland" -msgstr "" +msgstr "Finland" #. module: base #: selection:ir.actions.act_window,view_type:0 @@ -1407,7 +1407,7 @@ msgstr "" #. module: base #: view:base.language.export:0 msgid "https://help.launchpad.net/Translations" -msgstr "" +msgstr "https://help.launchpad.net/Translations" #. module: base #: field:ir.actions.act_window,view_mode:0 @@ -1430,7 +1430,7 @@ msgstr "" #. module: base #: view:res.log:0 msgid "Logs" -msgstr "" +msgstr "Logfiler" #. module: base #: selection:base.language.install,lang:0 @@ -1613,7 +1613,7 @@ msgstr "" #: selection:ir.translation,type:0 #: field:multi_company.default,field_id:0 msgid "Field" -msgstr "" +msgstr "Felt" #. module: base #: view:ir.rule:0 @@ -1623,14 +1623,14 @@ msgstr "" #. module: base #: model:res.country,name:base.fo msgid "Faroe Islands" -msgstr "" +msgstr "Færøerne" #. module: base #: selection:res.config.users,view:0 #: selection:res.config.view,view:0 #: selection:res.users,view:0 msgid "Simplified" -msgstr "" +msgstr "Forenklet" #. module: base #: model:res.country,name:base.st @@ -1640,7 +1640,7 @@ msgstr "" #. module: base #: selection:res.partner.address,type:0 msgid "Invoice" -msgstr "" +msgstr "Faktura" #. module: base #: selection:base.language.install,lang:0 @@ -1650,12 +1650,12 @@ msgstr "" #. module: base #: model:res.country,name:base.bb msgid "Barbados" -msgstr "" +msgstr "Barbados" #. module: base #: model:res.country,name:base.mg msgid "Madagascar" -msgstr "" +msgstr "Madagaskar" #. module: base #: code:addons/base/ir/ir_model.py:96 @@ -1674,12 +1674,12 @@ msgstr "" #: view:ir.ui.menu:0 #: field:ir.ui.menu,name:0 msgid "Menu" -msgstr "" +msgstr "Menu" #. module: base #: field:res.currency,rate:0 msgid "Current Rate" -msgstr "" +msgstr "Aktuel kurs" #. module: base #: field:ir.ui.view.custom,ref_id:0 @@ -1721,7 +1721,7 @@ msgstr "" #. module: base #: model:res.country,name:base.zw msgid "Zimbabwe" -msgstr "" +msgstr "Zimbabwe" #. module: base #: view:base.module.update:0 @@ -1736,7 +1736,7 @@ msgstr "" #. module: base #: field:ir.actions.server,email:0 msgid "Email Address" -msgstr "" +msgstr "E-mail adresse" #. module: base #: selection:base.language.install,lang:0 @@ -1752,12 +1752,12 @@ msgstr "" #. module: base #: model:res.country,name:base.tt msgid "Trinidad and Tobago" -msgstr "" +msgstr "Trinidad og Tobago" #. module: base #: model:res.country,name:base.lv msgid "Latvia" -msgstr "" +msgstr "Letland" #. module: base #: view:ir.values:0 @@ -1782,7 +1782,7 @@ msgstr "" #. module: base #: model:res.country,name:base.py msgid "Paraguay" -msgstr "" +msgstr "Paraguay" #. module: base #: model:ir.model,name:base.model_ir_actions_act_window_close @@ -1797,7 +1797,7 @@ msgstr "" #. module: base #: model:res.country,name:base.lt msgid "Lithuania" -msgstr "" +msgstr "Litauen" #. module: base #: model:ir.actions.act_window,name:base.action_view_partner_clear_ids @@ -1827,12 +1827,12 @@ msgstr "" #. module: base #: model:res.country,name:base.si msgid "Slovenia" -msgstr "" +msgstr "Slovenien" #. module: base #: model:res.country,name:base.pk msgid "Pakistan" -msgstr "" +msgstr "Pakistan" #. module: base #: code:addons/orm.py:1350 @@ -1843,7 +1843,7 @@ msgstr "" #. module: base #: model:ir.ui.menu,name:base.menu_email_gateway_form msgid "Messages" -msgstr "" +msgstr "Meddelelser" #. module: base #: code:addons/base/ir/ir_model.py:303 @@ -1855,7 +1855,7 @@ msgstr "" #: code:addons/base/module/wizard/base_update_translations.py:38 #, python-format msgid "Error!" -msgstr "" +msgstr "Fejl!" #. module: base #: view:res.lang:0 @@ -1880,7 +1880,7 @@ msgstr "" #. module: base #: model:res.country,name:base.nz msgid "New Zealand" -msgstr "" +msgstr "New Zealand" #. module: base #: code:addons/orm.py:3366 @@ -1927,7 +1927,7 @@ msgstr "" #. module: base #: model:res.country,name:base.bd msgid "Bangladesh" -msgstr "" +msgstr "Bangladesh" #. module: base #: constraint:res.company:0 @@ -1953,7 +1953,7 @@ msgstr "" #. module: base #: model:res.country,name:base.cu msgid "Cuba" -msgstr "" +msgstr "Cuba" #. module: base #: model:ir.model,name:base.model_res_partner_event @@ -1963,12 +1963,12 @@ msgstr "" #. module: base #: model:res.widget,title:base.facebook_widget msgid "Facebook" -msgstr "" +msgstr "Facebook" #. module: base #: model:res.country,name:base.am msgid "Armenia" -msgstr "" +msgstr "Armenien" #. module: base #: model:ir.actions.act_window,name:base.ir_property_form @@ -1984,14 +1984,14 @@ msgstr "" #. module: base #: model:res.country,name:base.se msgid "Sweden" -msgstr "" +msgstr "Sverige" #. module: base #: selection:ir.actions.act_window.view,view_mode:0 #: selection:ir.ui.view,type:0 #: selection:wizard.ir.model.menu.create.line,view_type:0 msgid "Gantt" -msgstr "" +msgstr "Gantt" #. module: base #: view:ir.property:0 @@ -2002,7 +2002,7 @@ msgstr "" #: model:ir.model,name:base.model_res_partner_bank_type #: view:res.partner.bank.type:0 msgid "Bank Account Type" -msgstr "" +msgstr "Bank Kontotype" #. module: base #: field:base.language.export,config_logo:0 @@ -2019,7 +2019,7 @@ msgstr "" #: field:res.config.users,config_logo:0 #: field:res.config.view,config_logo:0 msgid "Image" -msgstr "" +msgstr "Billede" #. module: base #: view:ir.actions.server:0 @@ -2034,7 +2034,7 @@ msgstr "" #. module: base #: model:res.country,name:base.at msgid "Austria" -msgstr "" +msgstr "Østrig" #. module: base #: selection:base.language.install,state:0 @@ -2049,7 +2049,7 @@ msgstr "" #: selection:ir.ui.view,type:0 #: selection:wizard.ir.model.menu.create.line,view_type:0 msgid "Calendar" -msgstr "" +msgstr "Kalender" #. module: base #: field:res.partner.address,partner_id:0 @@ -2143,7 +2143,7 @@ msgstr "" #. module: base #: field:res.partner.address,birthdate:0 msgid "Birthdate" -msgstr "" +msgstr "Fødselsdato" #. module: base #: model:ir.actions.act_window,name:base.action_partner_title_contact @@ -2183,12 +2183,12 @@ msgstr "" #. module: base #: model:res.country,name:base.uy msgid "Uruguay" -msgstr "" +msgstr "Uruguay" #. module: base #: selection:base.language.install,lang:0 msgid "Finnish / Suomi" -msgstr "" +msgstr "Finsk / Suomi" #. module: base #: field:ir.rule,perm_write:0 @@ -2203,7 +2203,7 @@ msgstr "" #. module: base #: selection:base.language.install,lang:0 msgid "German / Deutsch" -msgstr "" +msgstr "Tysk / Deutsch" #. module: base #: help:ir.actions.server,trigger_name:0 @@ -2218,7 +2218,7 @@ msgstr "" #. module: base #: selection:base.language.install,lang:0 msgid "Portugese / Português" -msgstr "" +msgstr "Portugisisk / Português" #. module: base #: model:res.partner.title,name:base.res_partner_title_sir @@ -2245,7 +2245,7 @@ msgstr "" #. module: base #: model:res.country,name:base.mt msgid "Malta" -msgstr "" +msgstr "Malta" #. module: base #: field:ir.actions.server,fields_lines:0 @@ -2261,7 +2261,7 @@ msgstr "" #: report:ir.module.reference.graph:0 #: field:ir.translation,module:0 msgid "Module" -msgstr "" +msgstr "Modul" #. module: base #: field:ir.attachment,description:0 @@ -2272,7 +2272,7 @@ msgstr "" #: field:res.partner.event,description:0 #: view:res.request:0 msgid "Description" -msgstr "" +msgstr "Beskrivelse" #. module: base #: model:ir.actions.act_window,name:base.action_workflow_instance_form @@ -2283,7 +2283,7 @@ msgstr "" #. module: base #: model:res.country,name:base.aq msgid "Antarctica" -msgstr "" +msgstr "Antarktis" #. module: base #: field:ir.actions.report.xml,auto:0 @@ -2336,7 +2336,7 @@ msgstr "" #. module: base #: view:res.payterm:0 msgid "Payment Term" -msgstr "" +msgstr "Betalingsbetingelse" #. module: base #: selection:res.lang,direction:0 @@ -2417,7 +2417,7 @@ msgstr "" #. module: base #: model:res.country,name:base.ru msgid "Russian Federation" -msgstr "" +msgstr "Rusland" #. module: base #: selection:base.language.install,lang:0 @@ -2427,13 +2427,13 @@ msgstr "" #. module: base #: field:res.company,name:0 msgid "Company Name" -msgstr "" +msgstr "Virksomhedsnavn" #. module: base #: model:ir.actions.act_window,name:base.action_country #: model:ir.ui.menu,name:base.menu_country_partner msgid "Countries" -msgstr "" +msgstr "Lande" #. module: base #: selection:ir.translation,type:0 @@ -2448,7 +2448,7 @@ msgstr "" #. module: base #: view:ir.property:0 msgid "Field Information" -msgstr "" +msgstr "Feltinformation" #. module: base #: view:ir.actions.todo:0 @@ -2464,7 +2464,7 @@ msgstr "" #. module: base #: field:res.partner,vat:0 msgid "VAT" -msgstr "" +msgstr "Moms" #. module: base #: view:res.lang:0 @@ -2545,7 +2545,7 @@ msgstr "" #. module: base #: model:res.country,name:base.me msgid "Montenegro" -msgstr "" +msgstr "Montenegro" #. module: base #: view:ir.cron:0 @@ -2556,7 +2556,7 @@ msgstr "" #: view:res.partner:0 #: field:res.partner,category_id:0 msgid "Categories" -msgstr "" +msgstr "Kategorier" #. module: base #: view:base.language.import:0 @@ -2576,7 +2576,7 @@ msgstr "" #. module: base #: model:res.country,name:base.ly msgid "Libya" -msgstr "" +msgstr "Libyen" #. module: base #: model:res.country,name:base.cf @@ -2586,18 +2586,18 @@ msgstr "" #. module: base #: model:res.country,name:base.li msgid "Liechtenstein" -msgstr "" +msgstr "Liechtenstein" #. module: base #: model:ir.model,name:base.model_partner_sms_send #: view:partner.sms.send:0 msgid "Send SMS" -msgstr "" +msgstr "Send SMS" #. module: base #: field:res.partner,ean13:0 msgid "EAN13" -msgstr "" +msgstr "EAN13" #. module: base #: code:addons/orm.py:1622 @@ -2608,7 +2608,7 @@ msgstr "" #. module: base #: model:res.country,name:base.pt msgid "Portugal" -msgstr "" +msgstr "Portugal" #. module: base #: sql_constraint:ir.model.data:0 @@ -2648,7 +2648,7 @@ msgstr "" #: model:ir.ui.menu,name:base.menu_res_lang_act_window #: view:res.lang:0 msgid "Languages" -msgstr "" +msgstr "Sprog" #. module: base #: selection:workflow.activity,join_mode:0 @@ -2659,7 +2659,7 @@ msgstr "" #. module: base #: model:res.country,name:base.ec msgid "Ecuador" -msgstr "" +msgstr "Equador" #. module: base #: code:addons/base/module/wizard/base_export_language.py:52 @@ -2676,12 +2676,12 @@ msgstr "" #: model:ir.ui.menu,name:base.menu_partner_form #: view:res.partner:0 msgid "Customers" -msgstr "" +msgstr "Kunder" #. module: base #: model:res.country,name:base.au msgid "Australia" -msgstr "" +msgstr "Australien" #. module: base #: help:res.partner,lang:0 @@ -2693,7 +2693,7 @@ msgstr "" #. module: base #: report:ir.module.reference.graph:0 msgid "Menu :" -msgstr "" +msgstr "Menu:" #. module: base #: selection:ir.model.fields,state:0 @@ -2708,7 +2708,7 @@ msgstr "" #. module: base #: field:ir.actions.todo,restart:0 msgid "Restart" -msgstr "" +msgstr "Genstart" #. module: base #: field:ir.actions.report.xml,report_sxw_content:0 @@ -2776,7 +2776,7 @@ msgstr "" #. module: base #: view:res.company:0 msgid "Header/Footer" -msgstr "" +msgstr "Sidehoved/sidefod" #. module: base #: help:ir.actions.act_window,help:0 @@ -2829,13 +2829,13 @@ msgstr "" #. module: base #: model:ir.ui.menu,name:base.marketing_menu msgid "Marketing" -msgstr "" +msgstr "Markedsføring" #. module: base #: view:res.partner.bank:0 #: model:res.partner.bank.type,name:base.bank_normal msgid "Bank account" -msgstr "" +msgstr "Bank konto" #. module: base #: selection:base.language.install,lang:0 @@ -2855,17 +2855,17 @@ msgstr "" #. module: base #: field:ir.module.module,license:0 msgid "License" -msgstr "" +msgstr "Licens" #. module: base #: field:ir.attachment,url:0 msgid "Url" -msgstr "" +msgstr "Adresse" #. module: base #: selection:ir.actions.todo,restart:0 msgid "Always" -msgstr "" +msgstr "Altid" #. module: base #: selection:ir.translation,type:0 @@ -2876,7 +2876,7 @@ msgstr "" #: field:ir.actions.server,srcmodel_id:0 #: field:ir.model.fields,model_id:0 msgid "Model" -msgstr "" +msgstr "Model" #. module: base #: view:base.language.install:0 @@ -2911,7 +2911,7 @@ msgstr "" #: field:res.partner.address,zip:0 #: field:res.partner.bank,zip:0 msgid "Zip" -msgstr "" +msgstr "Postnummer" #. module: base #: view:ir.module.module:0 @@ -2946,12 +2946,12 @@ msgstr "" #. module: base #: model:res.country,name:base.bo msgid "Bolivia" -msgstr "" +msgstr "Bolivia" #. module: base #: model:res.country,name:base.gh msgid "Ghana" -msgstr "" +msgstr "Ghana" #. module: base #: field:res.lang,direction:0 @@ -2973,7 +2973,7 @@ msgstr "" #: view:res.groups:0 #: field:res.groups,rule_groups:0 msgid "Rules" -msgstr "" +msgstr "Regler" #. module: base #: code:addons/base/module/module.py:216 @@ -3040,7 +3040,7 @@ msgstr "" #: view:res.config:0 #: view:res.config.installer:0 msgid "Skip" -msgstr "" +msgstr "Spring over" #. module: base #: model:res.country,name:base.ls @@ -3056,7 +3056,7 @@ msgstr "" #. module: base #: model:res.country,name:base.ke msgid "Kenya" -msgstr "" +msgstr "Kenya" #. module: base #: view:res.partner.event:0 @@ -3092,17 +3092,17 @@ msgstr "" #. module: base #: model:res.country,name:base.sm msgid "San Marino" -msgstr "" +msgstr "San Marino" #. module: base #: model:res.country,name:base.bm msgid "Bermuda" -msgstr "" +msgstr "Bermuda" #. module: base #: model:res.country,name:base.pe msgid "Peru" -msgstr "" +msgstr "Peru" #. module: base #: selection:ir.model.fields,on_delete:0 @@ -3162,7 +3162,7 @@ msgstr "" #: view:ir.model.access:0 #: view:ir.rule:0 msgid "Full Access" -msgstr "" +msgstr "Fuld adgang" #. module: base #: view:ir.actions.act_window:0 @@ -3171,7 +3171,7 @@ msgstr "" #: view:ir.model.fields:0 #: model:ir.ui.menu,name:base.menu_security msgid "Security" -msgstr "" +msgstr "Sikkerhed" #. module: base #: model:res.widget,title:base.openerp_favorites_twitter_widget @@ -3181,14 +3181,14 @@ msgstr "" #. module: base #: model:res.country,name:base.za msgid "South Africa" -msgstr "" +msgstr "Sydafrika" #. module: base #: view:ir.module.module:0 #: selection:ir.module.module,state:0 #: selection:ir.module.module.dependency,state:0 msgid "Installed" -msgstr "" +msgstr "Installeret" #. module: base #: selection:base.language.install,lang:0 @@ -3204,12 +3204,12 @@ msgstr "" #. module: base #: model:res.country,name:base.sn msgid "Senegal" -msgstr "" +msgstr "Senegal" #. module: base #: model:res.country,name:base.hu msgid "Hungary" -msgstr "" +msgstr "Ungarn" #. module: base #: model:ir.model,name:base.model_res_groups @@ -3219,7 +3219,7 @@ msgstr "" #. module: base #: model:res.country,name:base.br msgid "Brazil" -msgstr "" +msgstr "Brasilien" #. module: base #: view:res.lang:0 @@ -3234,7 +3234,7 @@ msgstr "" #. module: base #: field:ir.sequence,number_next:0 msgid "Next Number" -msgstr "" +msgstr "Næste nummer" #. module: base #: help:workflow.transition,condition:0 @@ -3255,12 +3255,12 @@ msgstr "" #. module: base #: model:res.country,name:base.sy msgid "Syria" -msgstr "" +msgstr "Syrien" #. module: base #: view:res.lang:0 msgid "======================================================" -msgstr "" +msgstr "======================================================" #. module: base #: help:ir.actions.server,mobile:0 @@ -3288,7 +3288,7 @@ msgstr "" #: field:res.partner.event,date:0 #: field:res.request,date_sent:0 msgid "Date" -msgstr "" +msgstr "Dato" #. module: base #: field:ir.actions.report.xml,report_sxw:0 @@ -3298,7 +3298,7 @@ msgstr "" #. module: base #: view:ir.attachment:0 msgid "Data" -msgstr "" +msgstr "Data" #. module: base #: field:ir.ui.menu,parent_id:0 @@ -3364,7 +3364,7 @@ msgstr "" #. module: base #: model:res.country,name:base.mx msgid "Mexico" -msgstr "" +msgstr "Mexico" #. module: base #: model:ir.ui.menu,name:base.menu_base_config_plugins @@ -3384,7 +3384,7 @@ msgstr "" #. module: base #: model:res.country,name:base.ni msgid "Nicaragua" -msgstr "" +msgstr "Nicaragua" #. module: base #: code:addons/orm.py:1046 @@ -3416,7 +3416,7 @@ msgstr "" #. module: base #: model:res.country,name:base.ve msgid "Venezuela" -msgstr "" +msgstr "Venezuela" #. module: base #: view:res.lang:0 @@ -3426,7 +3426,7 @@ msgstr "" #. module: base #: model:res.country,name:base.zm msgid "Zambia" -msgstr "" +msgstr "Zambia" #. module: base #: help:res.partner,user_id:0 @@ -3453,7 +3453,7 @@ msgstr "" #. module: base #: model:res.country,name:base.kz msgid "Kazakhstan" -msgstr "" +msgstr "Kazakstan" #. module: base #: view:res.lang:0 @@ -3536,17 +3536,17 @@ msgstr "" #. module: base #: field:ir.module.module,demo:0 msgid "Demo data" -msgstr "" +msgstr "Demostrations data" #. module: base #: selection:base.language.install,lang:0 msgid "English (UK)" -msgstr "" +msgstr "Engelsk (UK)" #. module: base #: selection:base.language.install,lang:0 msgid "Japanese / 日本語" -msgstr "" +msgstr "Japansk / 日本語" #. module: base #: help:workflow.transition,act_from:0 @@ -3580,7 +3580,7 @@ msgstr "" #. module: base #: selection:base.language.install,lang:0 msgid "English (CA)" -msgstr "" +msgstr "Engelsk (CA)" #. module: base #: model:ir.model,name:base.model_publisher_warranty_contract @@ -3590,7 +3590,7 @@ msgstr "" #. module: base #: model:res.country,name:base.et msgid "Ethiopia" -msgstr "" +msgstr "Etiopien" #. module: base #: help:res.country.state,code:0 @@ -3631,7 +3631,7 @@ msgstr "" #. module: base #: view:ir.translation:0 msgid "Translation" -msgstr "" +msgstr "Oversættelse" #. module: base #: selection:res.request,state:0 @@ -3689,7 +3689,7 @@ msgstr "" #: field:res.partner.bank,state:0 #: field:res.partner.bank.type.field,bank_type_id:0 msgid "Bank Type" -msgstr "" +msgstr "Bank type" #. module: base #: code:addons/base/res/res_user.py:58 @@ -3757,7 +3757,7 @@ msgstr "" #. module: base #: selection:ir.cron,interval_type:0 msgid "Hours" -msgstr "" +msgstr "Timer" #. module: base #: model:res.country,name:base.gp @@ -3770,7 +3770,7 @@ msgstr "" #: code:addons/base/res/res_lang.py:161 #, python-format msgid "User Error" -msgstr "" +msgstr "Bruger fejl!" #. module: base #: help:workflow.transition,signal:0 @@ -3803,18 +3803,18 @@ msgstr "" #. module: base #: view:ir.attachment:0 msgid "Month" -msgstr "" +msgstr "Måned" #. module: base #: model:res.country,name:base.my msgid "Malaysia" -msgstr "" +msgstr "Malaysien" #. module: base #: view:base.language.install:0 #: model:ir.actions.act_window,name:base.action_view_base_language_install msgid "Load Official Translation" -msgstr "" +msgstr "Hent den officielle oversættelse" #. module: base #: model:ir.model,name:base.model_res_request_history @@ -3893,7 +3893,7 @@ msgstr "" #. module: base #: view:res.currency:0 msgid "Price Accuracy" -msgstr "" +msgstr "Pris nøjagtighed" #. module: base #: selection:base.language.install,lang:0 @@ -3909,7 +3909,7 @@ msgstr "" #. module: base #: selection:base.language.install,lang:0 msgid "French / Français" -msgstr "" +msgstr "Fransk / Français" #. module: base #: code:addons/orm.py:1049 @@ -3971,7 +3971,7 @@ msgstr "" #. module: base #: model:res.country,name:base.fj msgid "Fiji" -msgstr "" +msgstr "Fiji" #. module: base #: field:ir.model.fields,size:0 @@ -3981,12 +3981,12 @@ msgstr "" #. module: base #: model:res.country,name:base.sd msgid "Sudan" -msgstr "" +msgstr "Sudan" #. module: base #: model:res.country,name:base.fm msgid "Micronesia" -msgstr "" +msgstr "Mikronesien" #. module: base #: view:res.request.history:0 @@ -3998,7 +3998,7 @@ msgstr "" #: field:ir.module.module,menus_by_module:0 #: view:res.groups:0 msgid "Menus" -msgstr "" +msgstr "Menuer" #. module: base #: selection:base.language.install,lang:0 @@ -4008,7 +4008,7 @@ msgstr "" #. module: base #: model:res.country,name:base.il msgid "Israel" -msgstr "" +msgstr "Israel" #. module: base #: model:ir.actions.wizard,name:base.wizard_server_action_create @@ -4025,7 +4025,7 @@ msgstr "" #. module: base #: field:res.lang,time_format:0 msgid "Time Format" -msgstr "" +msgstr "Tidsformat" #. module: base #: view:ir.module.module:0 @@ -4045,7 +4045,7 @@ msgstr "" #: model:ir.ui.menu,name:base.menu_management #: model:ir.ui.menu,name:base.menu_module_tree msgid "Modules" -msgstr "" +msgstr "Moduler" #. module: base #: view:workflow.activity:0 @@ -4071,12 +4071,12 @@ msgstr "" #: view:res.bank:0 #: field:res.partner,bank_ids:0 msgid "Banks" -msgstr "" +msgstr "Banker" #. module: base #: view:res.log:0 msgid "Unread" -msgstr "" +msgstr "Ulæst" #. module: base #: field:ir.cron,doall:0 @@ -4102,7 +4102,7 @@ msgstr "" #. module: base #: model:res.country,name:base.uk msgid "United Kingdom" -msgstr "" +msgstr "Storbritannien" #. module: base #: view:res.config:0 @@ -4124,7 +4124,7 @@ msgstr "" #. module: base #: model:res.country,name:base.bw msgid "Botswana" -msgstr "" +msgstr "Botswana" #. module: base #: model:ir.actions.act_window,name:base.action_partner_title_partner @@ -4213,7 +4213,7 @@ msgstr "" #. module: base #: model:ir.ui.menu,name:base.menu_main_pm msgid "Project" -msgstr "" +msgstr "Projekt" #. module: base #: field:ir.ui.menu,web_icon_hover_data:0 @@ -4274,7 +4274,7 @@ msgstr "" #. module: base #: field:res.partner,employee:0 msgid "Employee" -msgstr "" +msgstr "Ansat" #. module: base #: field:ir.model.access,perm_create:0 @@ -4289,7 +4289,7 @@ msgstr "" #. module: base #: field:ir.actions.server,copy_object:0 msgid "Copy Of" -msgstr "" +msgstr "Kopi af" #. module: base #: field:ir.model,osv_memory:0 @@ -4327,7 +4327,7 @@ msgstr "" #: view:ir.model:0 #: field:ir.model.fields,ttype:0 msgid "Field Type" -msgstr "" +msgstr "Felttype" #. module: base #: field:res.country.state,code:0 @@ -4353,14 +4353,14 @@ msgstr "" #. module: base #: model:res.country,name:base.vn msgid "Vietnam" -msgstr "" +msgstr "Vietnam" #. module: base #: field:res.config.users,signature:0 #: view:res.users:0 #: field:res.users,signature:0 msgid "Signature" -msgstr "" +msgstr "Signatur" #. module: base #: code:addons/fields.py:456 @@ -4372,7 +4372,7 @@ msgstr "" #: code:addons/fields.py:664 #, python-format msgid "Not Implemented" -msgstr "" +msgstr "Ikke implementeret" #. module: base #: model:ir.model,name:base.model_res_widget_user @@ -4382,7 +4382,7 @@ msgstr "" #. module: base #: field:res.partner.category,complete_name:0 msgid "Full Name" -msgstr "" +msgstr "Fulde navn" #. module: base #: view:base.module.configuration:0 @@ -4427,7 +4427,7 @@ msgstr "" #: view:res.partner:0 #: field:res.partner,user_id:0 msgid "Salesman" -msgstr "" +msgstr "Sælger" #. module: base #: field:res.partner,address:0 @@ -4462,7 +4462,7 @@ msgstr "" #. module: base #: model:res.country,name:base.cz msgid "Czech Republic" -msgstr "" +msgstr "Tjekkiet" #. module: base #: view:res.widget.wizard:0 @@ -4527,12 +4527,12 @@ msgstr "" #. module: base #: model:res.country,name:base.na msgid "Namibia" -msgstr "" +msgstr "Namibia" #. module: base #: model:res.country,name:base.mn msgid "Mongolia" -msgstr "" +msgstr "Mongoliet" #. module: base #: view:ir.module.module:0 @@ -4547,7 +4547,7 @@ msgstr "" #. module: base #: model:res.country,name:base.bi msgid "Burundi" -msgstr "" +msgstr "Burundi" #. module: base #: view:base.language.install:0 @@ -4568,12 +4568,12 @@ msgstr "" #. module: base #: view:res.log:0 msgid "My Logs" -msgstr "" +msgstr "Mine logfiler" #. module: base #: model:res.country,name:base.bt msgid "Bhutan" -msgstr "" +msgstr "Bhutan" #. module: base #: help:ir.sequence,number_next:0 @@ -4603,7 +4603,7 @@ msgstr "" #. module: base #: field:base.language.export,format:0 msgid "File Format" -msgstr "" +msgstr "Filformat" #. module: base #: field:res.lang,iso_code:0 @@ -4619,7 +4619,7 @@ msgstr "" #: view:res.log:0 #: field:res.log,read:0 msgid "Read" -msgstr "" +msgstr "Læst" #. module: base #: sql_constraint:res.country:0 @@ -4649,7 +4649,7 @@ msgstr "" #: field:res.config.users,password:0 #: field:res.users,password:0 msgid "Password" -msgstr "" +msgstr "Adgangskode" #. module: base #: model:ir.actions.act_window,name:base.action_model_fields @@ -4659,12 +4659,12 @@ msgstr "" #: view:ir.model.fields:0 #: model:ir.ui.menu,name:base.ir_model_model_fields msgid "Fields" -msgstr "" +msgstr "Felter" #. module: base #: model:ir.actions.act_window,name:base.action_partner_employee_form msgid "Employees" -msgstr "" +msgstr "Ansatte" #. module: base #: help:res.log,read:0 @@ -4705,12 +4705,12 @@ msgstr "" #: model:ir.actions.act_window,name:base.action_partner_address_form #: model:ir.ui.menu,name:base.menu_partner_address_form msgid "Addresses" -msgstr "" +msgstr "Adresser" #. module: base #: model:res.country,name:base.mm msgid "Myanmar" -msgstr "" +msgstr "Myanmar (Burma)" #. module: base #: selection:base.language.install,lang:0 @@ -4722,12 +4722,12 @@ msgstr "" #: field:res.partner.address,street:0 #: field:res.partner.bank,street:0 msgid "Street" -msgstr "" +msgstr "Vej" #. module: base #: model:res.country,name:base.yu msgid "Yugoslavia" -msgstr "" +msgstr "Jugoslavien" #. module: base #: field:ir.model.data,name:0 @@ -4737,12 +4737,12 @@ msgstr "" #. module: base #: model:res.country,name:base.ca msgid "Canada" -msgstr "" +msgstr "Canada" #. module: base #: selection:ir.module.module.dependency,state:0 msgid "Unknown" -msgstr "" +msgstr "Ukendt" #. module: base #: model:ir.actions.act_window,name:base.action_res_users_my @@ -4758,17 +4758,17 @@ msgstr "" #. module: base #: field:partner.sms.send,text:0 msgid "SMS Message" -msgstr "" +msgstr "SMS besked" #. module: base #: model:res.country,name:base.cm msgid "Cameroon" -msgstr "" +msgstr "Cameroun" #. module: base #: model:res.country,name:base.bf msgid "Burkina Faso" -msgstr "" +msgstr "Burkina Faso" #. module: base #: selection:ir.actions.todo,state:0 @@ -4835,7 +4835,7 @@ msgstr "" #. module: base #: report:ir.module.reference.graph:0 msgid "1cm 28cm 20cm 28cm" -msgstr "" +msgstr "1cm 28cm 20cm 28cm" #. module: base #: field:ir.module.module,maintainer:0 @@ -4855,7 +4855,7 @@ msgstr "" #. module: base #: model:ir.actions.report.xml,name:base.res_partner_address_report msgid "Labels" -msgstr "" +msgstr "Etiketter" #. module: base #: field:partner.wizard.spam,email_from:0 @@ -4945,7 +4945,7 @@ msgstr "" #. module: base #: model:res.country,name:base.us msgid "United States" -msgstr "" +msgstr "USA" #. module: base #: view:ir.module.module:0 @@ -4978,7 +4978,7 @@ msgstr "" #. module: base #: model:res.country,name:base.kw msgid "Kuwait" -msgstr "" +msgstr "Kuwait" #. module: base #: field:workflow.workitem,inst_id:0 @@ -5001,7 +5001,7 @@ msgstr "" #. module: base #: model:res.country,name:base.ng msgid "Nigeria" -msgstr "" +msgstr "Nigeria" #. module: base #: code:addons/base/ir/ir_model.py:250 @@ -5012,7 +5012,7 @@ msgstr "" #. module: base #: model:ir.actions.act_window,name:base.action_partner_sms_send msgid "SMS Send" -msgstr "" +msgstr "SMS sendt" #. module: base #: field:res.company,user_ids:0 @@ -5037,7 +5037,7 @@ msgstr "" #. module: base #: model:res.country,name:base.hk msgid "Hong Kong" -msgstr "" +msgstr "Hong Kong" #. module: base #: help:ir.actions.server,name:0 @@ -5059,12 +5059,12 @@ msgstr "" #. module: base #: model:res.country,name:base.ph msgid "Philippines" -msgstr "" +msgstr "Filippinerne" #. module: base #: model:res.country,name:base.ma msgid "Morocco" -msgstr "" +msgstr "Marokko" #. module: base #: view:res.lang:0 @@ -5084,7 +5084,7 @@ msgstr "" #. module: base #: model:res.country,name:base.td msgid "Chad" -msgstr "" +msgstr "Tchad" #. module: base #: model:ir.model,name:base.model_workflow_transition @@ -5131,7 +5131,7 @@ msgstr "" #. module: base #: model:res.country,name:base.np msgid "Nepal" -msgstr "" +msgstr "Nepal" #. module: base #: code:addons/orm.py:2307 @@ -5233,12 +5233,12 @@ msgstr "" #: field:base.language.export,data:0 #: field:base.language.import,data:0 msgid "File" -msgstr "" +msgstr "Fil" #. module: base #: view:res.config.users:0 msgid "Add User" -msgstr "" +msgstr "Tilføj bruger" #. module: base #: model:ir.actions.act_window,name:base.action_view_base_module_upgrade_install @@ -5261,7 +5261,7 @@ msgstr "" #: field:res.partner.address,is_supplier_add:0 #: model:res.partner.category,name:base.res_partner_category_8 msgid "Supplier" -msgstr "" +msgstr "Leverandør" #. module: base #: view:ir.actions.server:0 @@ -5349,7 +5349,7 @@ msgstr "" #. module: base #: model:res.country,name:base.ae msgid "United Arab Emirates" -msgstr "" +msgstr "De Forenede Arabiske Emirater" #. module: base #: model:ir.ui.menu,name:base.menu_crm_case_job_req_main @@ -5373,7 +5373,7 @@ msgstr "" #: view:ir.rule:0 #: field:ir.rule,global:0 msgid "Global" -msgstr "" +msgstr "Globalt" #. module: base #: model:res.country,name:base.mp @@ -5427,7 +5427,7 @@ msgstr "" #: view:ir.translation:0 #: model:ir.ui.menu,name:base.menu_translation msgid "Translations" -msgstr "" +msgstr "Oversættelser" #. module: base #: field:ir.sequence,padding:0 @@ -5437,12 +5437,12 @@ msgstr "" #. module: base #: view:ir.actions.report.xml:0 msgid "Report" -msgstr "" +msgstr "Rapport" #. module: base #: model:res.country,name:base.ua msgid "Ukraine" -msgstr "" +msgstr "Ukraine" #. module: base #: model:res.country,name:base.to @@ -5558,12 +5558,12 @@ msgstr "" #. module: base #: model:res.country,name:base.dz msgid "Algeria" -msgstr "" +msgstr "Algeriet" #. module: base #: model:res.country,name:base.be msgid "Belgium" -msgstr "" +msgstr "Belgien" #. module: base #: model:ir.model,name:base.model_osv_memory_autovacuum @@ -5579,12 +5579,12 @@ msgstr "" #: field:res.partner,lang:0 #: field:res.users,context_lang:0 msgid "Language" -msgstr "" +msgstr "Sprog" #. module: base #: model:res.country,name:base.gm msgid "Gambia" -msgstr "" +msgstr "Gambia" #. module: base #: model:ir.actions.act_window,name:base.action_res_company_form @@ -5596,7 +5596,7 @@ msgstr "" #: view:res.users:0 #: field:res.users,company_ids:0 msgid "Companies" -msgstr "" +msgstr "Virksomheder" #. module: base #: view:res.lang:0 @@ -5661,12 +5661,12 @@ msgstr "" #. module: base #: selection:base.language.export,format:0 msgid "PO File" -msgstr "" +msgstr "PO fil" #. module: base #: model:res.country,name:base.nt msgid "Neutral Zone" -msgstr "" +msgstr "Neutral Zone" #. module: base #: selection:base.language.install,lang:0 @@ -5686,7 +5686,7 @@ msgstr "" #. module: base #: model:res.partner.category,name:base.res_partner_category_9 msgid "Components Supplier" -msgstr "" +msgstr "Komponent leverandør" #. module: base #: model:ir.actions.act_window,name:base.action_res_users @@ -5697,7 +5697,7 @@ msgstr "" #: field:res.groups,users:0 #: view:res.users:0 msgid "Users" -msgstr "" +msgstr "Brugere" #. module: base #: field:ir.module.module,published_version:0 @@ -5707,7 +5707,7 @@ msgstr "" #. module: base #: model:res.country,name:base.is msgid "Iceland" -msgstr "" +msgstr "Island" #. module: base #: model:ir.actions.act_window,name:base.ir_action_window @@ -5728,7 +5728,7 @@ msgstr "" #. module: base #: model:res.country,name:base.de msgid "Germany" -msgstr "" +msgstr "Tyskland" #. module: base #: view:ir.sequence:0 @@ -5738,7 +5738,7 @@ msgstr "" #. module: base #: model:res.partner.category,name:base.res_partner_category_14 msgid "Bad customers" -msgstr "" +msgstr "Dårlige kunder" #. module: base #: report:ir.module.reference.graph:0 @@ -5748,7 +5748,7 @@ msgstr "" #. module: base #: model:res.country,name:base.gy msgid "Guyana" -msgstr "" +msgstr "Guyana" #. module: base #: help:ir.actions.act_window,view_type:0 @@ -5771,7 +5771,7 @@ msgstr "" #. module: base #: model:res.country,name:base.hn msgid "Honduras" -msgstr "" +msgstr "Honduras" #. module: base #: help:res.config.users,menu_tips:0 @@ -5783,7 +5783,7 @@ msgstr "" #. module: base #: model:res.country,name:base.eg msgid "Egypt" -msgstr "" +msgstr "Ægypten" #. module: base #: field:ir.rule,perm_read:0 @@ -5805,7 +5805,7 @@ msgstr "" #. module: base #: field:base.language.import,name:0 msgid "Language Name" -msgstr "" +msgstr "Sprog navn" #. module: base #: selection:ir.property,type:0 @@ -5886,7 +5886,7 @@ msgstr "" #: field:res.partner,comment:0 #: model:res.widget,title:base.note_widget msgid "Notes" -msgstr "" +msgstr "Noter" #. module: base #: field:ir.config_parameter,value:0 @@ -5911,7 +5911,7 @@ msgstr "" #: field:res.bank,code:0 #: field:res.partner.bank.type,code:0 msgid "Code" -msgstr "" +msgstr "Kode" #. module: base #: model:ir.model,name:base.model_res_config_installer @@ -5921,17 +5921,17 @@ msgstr "" #. module: base #: model:res.country,name:base.mc msgid "Monaco" -msgstr "" +msgstr "Monaco" #. module: base #: selection:ir.cron,interval_type:0 msgid "Minutes" -msgstr "" +msgstr "Minutter" #. module: base #: selection:ir.translation,type:0 msgid "Help" -msgstr "" +msgstr "Hjælp" #. module: base #: help:res.config.users,menu_id:0 @@ -5986,7 +5986,7 @@ msgstr "" #. module: base #: model:res.country,name:base.fr msgid "France" -msgstr "" +msgstr "Frankrig" #. module: base #: model:ir.model,name:base.model_res_log @@ -6008,7 +6008,7 @@ msgstr "" #. module: base #: selection:ir.cron,interval_type:0 msgid "Weeks" -msgstr "" +msgstr "Uger" #. module: base #: model:res.country,name:base.af @@ -6019,7 +6019,7 @@ msgstr "" #: code:addons/base/module/wizard/base_module_import.py:67 #, python-format msgid "Error !" -msgstr "" +msgstr "Fejl!" #. module: base #: model:res.partner.bank.type.field,name:base.bank_normal_field_contry @@ -6047,7 +6047,7 @@ msgstr "" #: field:res.bank,fax:0 #: field:res.partner.address,fax:0 msgid "Fax" -msgstr "" +msgstr "Fax" #. module: base #: field:res.lang,thousands_sep:0 @@ -6094,7 +6094,7 @@ msgstr "" #. module: base #: model:res.country,name:base.pa msgid "Panama" -msgstr "" +msgstr "Panama" #. module: base #: model:res.partner.title,name:base.res_partner_title_ltd @@ -6116,7 +6116,7 @@ msgstr "" #. module: base #: model:res.country,name:base.gi msgid "Gibraltar" -msgstr "" +msgstr "Gibraltar" #. module: base #: field:ir.actions.report.xml,report_name:0 @@ -6144,7 +6144,7 @@ msgstr "" #: field:res.config.users,name:0 #: field:res.users,name:0 msgid "User Name" -msgstr "" +msgstr "Brugernavn" #. module: base #: view:ir.sequence:0 @@ -6173,7 +6173,7 @@ msgstr "" #. module: base #: selection:ir.cron,interval_type:0 msgid "Months" -msgstr "" +msgstr "Måneder" #. module: base #: field:ir.actions.act_window,search_view:0 @@ -6198,7 +6198,7 @@ msgstr "" #: model:ir.ui.menu,name:base.menu_sale_config_sales #: model:ir.ui.menu,name:base.menu_sales msgid "Sales" -msgstr "" +msgstr "Salg" #. module: base #: field:ir.actions.server,child_ids:0 @@ -6234,17 +6234,17 @@ msgstr "" #: field:res.partner.address,city:0 #: field:res.partner.bank,city:0 msgid "City" -msgstr "" +msgstr "By" #. module: base #: model:res.country,name:base.qa msgid "Qatar" -msgstr "" +msgstr "Qatar" #. module: base #: model:res.country,name:base.it msgid "Italy" -msgstr "" +msgstr "Italien" #. module: base #: view:ir.actions.todo:0 @@ -6262,12 +6262,12 @@ msgstr "" #: field:res.partner,email:0 #: field:res.users,email:0 msgid "E-mail" -msgstr "" +msgstr "E-mail" #. module: base #: selection:ir.module.module,license:0 msgid "GPL-3 or later version" -msgstr "" +msgstr "GPL-3 eller senere version" #. module: base #: field:workflow.activity,action:0 @@ -6277,7 +6277,7 @@ msgstr "" #. module: base #: selection:base.language.install,lang:0 msgid "English (US)" -msgstr "" +msgstr "Engelsk (US)" #. module: base #: model:ir.actions.act_window,name:base.action_model_data @@ -6313,12 +6313,12 @@ msgstr "" #: view:res.users:0 #: field:res.users,address_id:0 msgid "Address" -msgstr "" +msgstr "Adresse" #. module: base #: field:ir.module.module,latest_version:0 msgid "Installed version" -msgstr "" +msgstr "Installeret version" #. module: base #: selection:base.language.install,lang:0 @@ -6328,7 +6328,7 @@ msgstr "" #. module: base #: model:res.country,name:base.mr msgid "Mauritania" -msgstr "" +msgstr "Mauretanien" #. module: base #: model:ir.model,name:base.model_ir_translation @@ -6344,7 +6344,7 @@ msgstr "" #: view:workflow.activity:0 #: field:workflow.workitem,act_id:0 msgid "Activity" -msgstr "" +msgstr "Aktivitet" #. module: base #: view:res.partner:0 @@ -6370,7 +6370,7 @@ msgstr "" #. module: base #: model:res.country,name:base.cg msgid "Congo" -msgstr "" +msgstr "Congo" #. module: base #: view:res.lang:0 @@ -6385,7 +6385,7 @@ msgstr "Standardværdi" #. module: base #: model:ir.ui.menu,name:base.menu_tools msgid "Tools" -msgstr "" +msgstr "Værktøj" #. module: base #: model:res.country,name:base.kn @@ -6427,7 +6427,7 @@ msgstr "" #: selection:ir.module.module,state:0 #: selection:ir.module.module.dependency,state:0 msgid "Not Installed" -msgstr "" +msgstr "Ikke installeret" #. module: base #: view:workflow.activity:0 @@ -6438,7 +6438,7 @@ msgstr "" #. module: base #: field:ir.ui.menu,icon:0 msgid "Icon" -msgstr "" +msgstr "Ikon" #. module: base #: help:ir.model.fields,model_id:0 @@ -6466,12 +6466,12 @@ msgstr "" #. module: base #: model:res.country,name:base.ye msgid "Yemen" -msgstr "" +msgstr "Yemen" #. module: base #: selection:workflow.activity,split_mode:0 msgid "Or" -msgstr "" +msgstr "Eller" #. module: base #: model:ir.actions.act_window,name:base.res_log_act_window @@ -6482,12 +6482,12 @@ msgstr "" #. module: base #: model:res.country,name:base.al msgid "Albania" -msgstr "" +msgstr "Albanien" #. module: base #: model:res.country,name:base.ws msgid "Samoa" -msgstr "" +msgstr "Samoa" #. module: base #: code:addons/base/res/res_lang.py:161 @@ -6555,14 +6555,14 @@ msgstr "" #. module: base #: model:res.country,name:base.la msgid "Laos" -msgstr "" +msgstr "Laos" #. module: base #: selection:ir.actions.server,state:0 #: field:res.config.users,user_email:0 #: field:res.users,user_email:0 msgid "Email" -msgstr "" +msgstr "E-mail" #. module: base #: field:res.config.users,action_id:0 @@ -6593,7 +6593,7 @@ msgstr "" #. module: base #: model:res.country,name:base.tg msgid "Togo" -msgstr "" +msgstr "Togo" #. module: base #: selection:ir.module.module,license:0 @@ -6603,7 +6603,7 @@ msgstr "" #. module: base #: selection:workflow.activity,kind:0 msgid "Stop All" -msgstr "" +msgstr "Stop alle" #. module: base #: code:addons/orm.py:412 @@ -6644,7 +6644,7 @@ msgstr "" #. module: base #: model:res.country,name:base.ro msgid "Romania" -msgstr "" +msgstr "Rumænien" #. module: base #: help:ir.cron,doall:0 @@ -6678,7 +6678,7 @@ msgstr "" #: field:res.config.users,context_tz:0 #: field:res.users,context_tz:0 msgid "Timezone" -msgstr "" +msgstr "Tidszone" #. module: base #: model:ir.model,name:base.model_ir_actions_report_xml @@ -6731,7 +6731,7 @@ msgstr "" #. module: base #: model:res.country,name:base.by msgid "Belarus" -msgstr "" +msgstr "Hviderusland" #. module: base #: field:ir.actions.act_window,name:0 @@ -6755,7 +6755,7 @@ msgstr "" #. module: base #: selection:res.request,priority:0 msgid "Normal" -msgstr "" +msgstr "Normal" #. module: base #: field:res.bank,street2:0 @@ -6786,12 +6786,12 @@ msgstr "" #: view:res.users:0 #: field:res.widget.user,user_id:0 msgid "User" -msgstr "" +msgstr "Bruger" #. module: base #: model:res.country,name:base.pr msgid "Puerto Rico" -msgstr "" +msgstr "Puerto Rico" #. module: base #: view:ir.actions.act_window:0 @@ -6816,7 +6816,7 @@ msgstr "" #. module: base #: model:res.country,name:base.ch msgid "Switzerland" -msgstr "" +msgstr "Schweiz" #. module: base #: model:res.country,name:base.gd @@ -6841,7 +6841,7 @@ msgstr "" #. module: base #: view:base.language.install:0 msgid "Load" -msgstr "" +msgstr "Indlæs" #. module: base #: help:res.config.users,name:0 @@ -6870,7 +6870,7 @@ msgstr "" #. module: base #: model:res.country,name:base.so msgid "Somalia" -msgstr "" +msgstr "Somalia" #. module: base #: selection:publisher_warranty.contract,state:0 @@ -6892,7 +6892,7 @@ msgstr "" #: field:res.request,act_to:0 #: field:res.request.history,act_to:0 msgid "To" -msgstr "" +msgstr "Til" #. module: base #: view:ir.cron:0 @@ -6909,12 +6909,12 @@ msgstr "" #. module: base #: selection:ir.module.module,license:0 msgid "GPL Version 2" -msgstr "" +msgstr "GPL Version 2" #. module: base #: selection:ir.module.module,license:0 msgid "GPL Version 3" -msgstr "" +msgstr "GPL Version 3" #. module: base #: code:addons/orm.py:836 @@ -6939,7 +6939,7 @@ msgstr "" #: field:res.partner.address,is_customer_add:0 #: model:res.partner.category,name:base.res_partner_category_0 msgid "Customer" -msgstr "" +msgstr "Kunde" #. module: base #: selection:base.language.install,lang:0 @@ -6949,7 +6949,7 @@ msgstr "" #. module: base #: field:ir.module.module,shortdesc:0 msgid "Short Description" -msgstr "" +msgstr "Kort beskrivelse" #. module: base #: field:ir.actions.act_window,context:0 @@ -6975,7 +6975,7 @@ msgstr "" #. module: base #: field:res.request.history,date_sent:0 msgid "Date sent" -msgstr "" +msgstr "Dato sendt" #. module: base #: view:ir.sequence:0 @@ -7002,12 +7002,12 @@ msgstr "" #. module: base #: model:res.country,name:base.tn msgid "Tunisia" -msgstr "" +msgstr "Tunesien" #. module: base #: model:ir.ui.menu,name:base.menu_mrp_root msgid "Manufacturing" -msgstr "" +msgstr "Produktion" #. module: base #: model:res.country,name:base.km @@ -7153,12 +7153,12 @@ msgstr "" #: code:addons/base/res/res_user.py:580 #, python-format msgid "Warning !" -msgstr "" +msgstr "Advarsel!" #. module: base #: model:res.widget,title:base.google_maps_widget msgid "Google Maps" -msgstr "" +msgstr "Google Maps" #. module: base #: model:ir.ui.menu,name:base.menu_base_config @@ -7210,17 +7210,17 @@ msgstr "" #. module: base #: model:res.country,name:base.tr msgid "Turkey" -msgstr "" +msgstr "Tyrkiet" #. module: base #: model:res.country,name:base.fk msgid "Falkland Islands" -msgstr "" +msgstr "Falklandsøerne" #. module: base #: model:res.country,name:base.lb msgid "Lebanon" -msgstr "" +msgstr "Libanon" #. module: base #: view:ir.actions.report.xml:0 @@ -7263,7 +7263,7 @@ msgstr "" #: view:base.language.install:0 #: model:ir.ui.menu,name:base.menu_view_base_language_install msgid "Load an Official Translation" -msgstr "" +msgstr "Hent en officiel oversættelse" #. module: base #: view:res.currency:0 @@ -7375,7 +7375,7 @@ msgstr "" #: view:ir.module.module:0 #: field:ir.module.module,category_id:0 msgid "Category" -msgstr "" +msgstr "Kategori" #. module: base #: view:ir.attachment:0 @@ -7388,17 +7388,17 @@ msgstr "" #: field:ir.actions.server,sms:0 #: selection:ir.actions.server,state:0 msgid "SMS" -msgstr "" +msgstr "SMS" #. module: base #: model:res.country,name:base.cr msgid "Costa Rica" -msgstr "" +msgstr "Costa Rica" #. module: base #: view:workflow.activity:0 msgid "Conditions" -msgstr "" +msgstr "Betingelser" #. module: base #: model:ir.actions.act_window,name:base.action_partner_other_form @@ -7410,7 +7410,7 @@ msgstr "" #: model:ir.ui.menu,name:base.menu_action_currency_form #: view:res.currency:0 msgid "Currencies" -msgstr "" +msgstr "Valutaer" #. module: base #: sql_constraint:res.groups:0 @@ -7435,12 +7435,12 @@ msgstr "" #. module: base #: model:res.country,name:base.dk msgid "Denmark" -msgstr "" +msgstr "Danmark" #. module: base #: field:res.country,code:0 msgid "Country Code" -msgstr "" +msgstr "Lande kode" #. module: base #: model:ir.model,name:base.model_workflow_instance @@ -7485,7 +7485,7 @@ msgstr "" #. module: base #: model:res.country,name:base.ee msgid "Estonia" -msgstr "" +msgstr "Estland" #. module: base #: model:ir.ui.menu,name:base.dashboard @@ -7506,7 +7506,7 @@ msgstr "" #. module: base #: model:res.country,name:base.nl msgid "Netherlands" -msgstr "" +msgstr "Holland" #. module: base #: model:ir.ui.menu,name:base.next_id_4 @@ -7541,7 +7541,7 @@ msgstr "" #: model:ir.ui.menu,name:base.menu_emails #: model:ir.ui.menu,name:base.menu_mail_gateway msgid "Emails" -msgstr "" +msgstr "E-mails" #. module: base #: model:res.country,name:base.cd @@ -7563,7 +7563,7 @@ msgstr "" #. module: base #: model:res.country,name:base.jp msgid "Japan" -msgstr "" +msgstr "Japan" #. module: base #: field:ir.cron,numbercall:0 @@ -7591,7 +7591,7 @@ msgstr "" #. module: base #: model:res.country,name:base.gr msgid "Greece" -msgstr "" +msgstr "Grækenland" #. module: base #: field:res.request,trigger_date:0 @@ -7643,7 +7643,7 @@ msgstr "" #: view:ir.model.fields:0 #: field:ir.model.fields,translate:0 msgid "Translate" -msgstr "" +msgstr "Oversæt" #. module: base #: field:res.request.history,body:0 @@ -7653,7 +7653,7 @@ msgstr "" #. module: base #: view:partner.wizard.spam:0 msgid "Send Email" -msgstr "" +msgstr "Send e-mail" #. module: base #: field:res.config.users,menu_id:0 @@ -7692,7 +7692,7 @@ msgstr "" #: model:ir.ui.menu,name:base.menu_procurement_management_supplier_name #: view:res.partner:0 msgid "Suppliers" -msgstr "" +msgstr "Leverandører" #. module: base #: view:publisher_warranty.contract.wizard:0 @@ -7729,12 +7729,12 @@ msgstr "" #. module: base #: model:res.country,name:base.gl msgid "Greenland" -msgstr "" +msgstr "Grønland" #. module: base #: field:res.partner.bank,acc_number:0 msgid "Account Number" -msgstr "" +msgstr "Kontonummer" #. module: base #: view:res.lang:0 @@ -7749,7 +7749,7 @@ msgstr "" #. module: base #: model:res.country,name:base.cy msgid "Cyprus" -msgstr "" +msgstr "Cypern" #. module: base #: view:base.module.import:0 @@ -7764,13 +7764,13 @@ msgstr "" #: field:partner.wizard.spam,subject:0 #: field:res.request,name:0 msgid "Subject" -msgstr "" +msgstr "Emne" #. module: base #: field:res.request,act_from:0 #: field:res.request.history,act_from:0 msgid "From" -msgstr "" +msgstr "Fra" #. module: base #: view:res.users:0 @@ -7811,7 +7811,7 @@ msgstr "" #. module: base #: model:res.country,name:base.cn msgid "China" -msgstr "" +msgstr "Kina" #. module: base #: code:addons/base/res/res_user.py:516 @@ -7841,7 +7841,7 @@ msgstr "" #. module: base #: model:res.country,name:base.id msgid "Indonesia" -msgstr "" +msgstr "Indonesien" #. module: base #: view:base.update.translations:0 @@ -7861,7 +7861,7 @@ msgstr "" #. module: base #: model:res.country,name:base.bg msgid "Bulgaria" -msgstr "" +msgstr "Bulgarien" #. module: base #: view:publisher_warranty.contract.wizard:0 @@ -7871,7 +7871,7 @@ msgstr "" #. module: base #: model:res.country,name:base.ao msgid "Angola" -msgstr "" +msgstr "Angola" #. module: base #: model:res.country,name:base.tf @@ -7886,7 +7886,7 @@ msgstr "" #: field:res.currency,name:0 #: field:res.currency.rate,currency_id:0 msgid "Currency" -msgstr "" +msgstr "Valuta" #. module: base #: field:res.partner.canal,name:0 @@ -7917,7 +7917,7 @@ msgstr "" #. module: base #: model:ir.ui.menu,name:base.menu_administration msgid "Administration" -msgstr "" +msgstr "Administration" #. module: base #: view:base.module.update:0 @@ -7971,12 +7971,12 @@ msgstr "" #. module: base #: model:res.country,name:base.ki msgid "Kiribati" -msgstr "" +msgstr "Kiribati" #. module: base #: model:res.country,name:base.iq msgid "Iraq" -msgstr "" +msgstr "Irak" #. module: base #: model:ir.ui.menu,name:base.menu_association @@ -7986,14 +7986,14 @@ msgstr "" #. module: base #: model:res.country,name:base.cl msgid "Chile" -msgstr "" +msgstr "Chile" #. module: base #: model:ir.ui.menu,name:base.menu_address_book #: model:ir.ui.menu,name:base.menu_config_address_book #: model:ir.ui.menu,name:base.menu_procurement_management_supplier msgid "Address Book" -msgstr "" +msgstr "Adressebog" #. module: base #: model:ir.model,name:base.model_ir_sequence_type @@ -8003,12 +8003,12 @@ msgstr "" #. module: base #: selection:base.language.export,format:0 msgid "CSV File" -msgstr "" +msgstr "CSV fil" #. module: base #: field:res.company,account_no:0 msgid "Account No." -msgstr "" +msgstr "Konto nummer" #. module: base #: code:addons/base/res/res_lang.py:157 @@ -8034,7 +8034,7 @@ msgstr "" #. module: base #: model:res.country,name:base.dj msgid "Djibouti" -msgstr "" +msgstr "Djibouti" #. module: base #: field:ir.translation,value:0 @@ -8044,7 +8044,7 @@ msgstr "" #. module: base #: model:res.country,name:base.ag msgid "Antigua and Barbuda" -msgstr "" +msgstr "Antigua og Barbuda" #. module: base #: code:addons/orm.py:3166 @@ -8057,7 +8057,7 @@ msgstr "" #. module: base #: model:res.country,name:base.zr msgid "Zaire" -msgstr "" +msgstr "Zaire" #. module: base #: field:ir.model.data,res_id:0 @@ -8091,7 +8091,7 @@ msgstr "" #. module: base #: view:res.request:0 msgid "Reply" -msgstr "" +msgstr "Svar" #. module: base #: selection:base.language.install,lang:0 @@ -8166,7 +8166,7 @@ msgstr "" #. module: base #: model:res.country,name:base.hr msgid "Croatia" -msgstr "" +msgstr "Kroatien" #. module: base #: help:res.bank,bic:0 @@ -8176,7 +8176,7 @@ msgstr "" #. module: base #: model:res.country,name:base.tm msgid "Turkmenistan" -msgstr "" +msgstr "Turkmenistan" #. module: base #: code:addons/base/ir/ir_actions.py:597 @@ -8208,7 +8208,7 @@ msgstr "" #: code:addons/orm.py:3199 #, python-format msgid "Error" -msgstr "" +msgstr "Fejl!" #. module: base #: model:res.country,name:base.pm @@ -8239,12 +8239,12 @@ msgstr "" #. module: base #: model:res.country,name:base.tz msgid "Tanzania" -msgstr "" +msgstr "Tanzania" #. module: base #: selection:base.language.install,lang:0 msgid "Danish / Dansk" -msgstr "" +msgstr "Danish / Dansk" #. module: base #: selection:ir.model.fields,select_level:0 @@ -8309,7 +8309,7 @@ msgstr "" #. module: base #: view:res.request:0 msgid "Send" -msgstr "" +msgstr "Send" #. module: base #: field:res.config.users,menu_tips:0 @@ -8370,7 +8370,7 @@ msgstr "" #. module: base #: model:res.country,name:base.do msgid "Dominican Republic" -msgstr "" +msgstr "Den Dominikanske Republik" #. module: base #: selection:base.language.install,lang:0 @@ -8388,7 +8388,7 @@ msgstr "" #. module: base #: model:res.country,name:base.sa msgid "Saudi Arabia" -msgstr "" +msgstr "Saudi-Arabien" #. module: base #: help:res.partner,supplier:0 @@ -8432,7 +8432,7 @@ msgstr "" #. module: base #: field:ir.actions.report.xml,report_xml:0 msgid "XML path" -msgstr "" +msgstr "XML sti" #. module: base #: selection:ir.actions.todo,restart:0 @@ -8442,12 +8442,12 @@ msgstr "" #. module: base #: model:res.country,name:base.gn msgid "Guinea" -msgstr "" +msgstr "Guinea" #. module: base #: model:res.country,name:base.lu msgid "Luxembourg" -msgstr "" +msgstr "Luxembourg" #. module: base #: help:ir.values,key2:0 @@ -8484,14 +8484,14 @@ msgstr "" #. module: base #: model:res.country,name:base.sv msgid "El Salvador" -msgstr "" +msgstr "El Salvador" #. module: base #: field:res.bank,phone:0 #: field:res.partner,phone:0 #: field:res.partner.address,phone:0 msgid "Phone" -msgstr "" +msgstr "Telefon" #. module: base #: field:ir.cron,active:0 @@ -8509,12 +8509,12 @@ msgstr "" #: view:workflow.instance:0 #: view:workflow.workitem:0 msgid "Active" -msgstr "" +msgstr "Aktiv" #. module: base #: model:res.country,name:base.th msgid "Thailand" -msgstr "" +msgstr "Thailand" #. module: base #: model:ir.ui.menu,name:base.menu_crm_config_lead @@ -8535,7 +8535,7 @@ msgstr "" #: selection:workflow.activity,join_mode:0 #: selection:workflow.activity,split_mode:0 msgid "And" -msgstr "" +msgstr "Og" #. module: base #: field:ir.model.fields,relation:0 @@ -8551,7 +8551,7 @@ msgstr "" #. module: base #: model:res.country,name:base.uz msgid "Uzbekistan" -msgstr "" +msgstr "Usbekistan" #. module: base #: model:ir.model,name:base.model_ir_actions_act_window @@ -8572,7 +8572,7 @@ msgstr "" #. module: base #: model:res.country,name:base.tw msgid "Taiwan" -msgstr "" +msgstr "Taiwan" #. module: base #: model:ir.model,name:base.model_res_currency_rate @@ -8682,7 +8682,7 @@ msgstr "" #: field:base.language.export,name:0 #: field:ir.attachment,datas_fname:0 msgid "Filename" -msgstr "" +msgstr "Filnavn" #. module: base #: field:ir.model,access_ids:0 @@ -8693,7 +8693,7 @@ msgstr "" #. module: base #: model:res.country,name:base.sk msgid "Slovak Republic" -msgstr "" +msgstr "Slovakiet" #. module: base #: model:ir.ui.menu,name:base.publisher_warranty @@ -8708,7 +8708,7 @@ msgstr "" #. module: base #: model:res.country,name:base.ar msgid "Argentina" -msgstr "" +msgstr "Argentina" #. module: base #: field:res.groups,name:0 @@ -8718,7 +8718,7 @@ msgstr "" #. module: base #: model:res.country,name:base.bh msgid "Bahrain" -msgstr "" +msgstr "Bahrain" #. module: base #: model:res.partner.category,name:base.res_partner_category_12 @@ -8740,7 +8740,7 @@ msgstr "" #: view:res.users:0 #: field:res.users,company_id:0 msgid "Company" -msgstr "" +msgstr "Virksomhed" #. module: base #: view:res.users:0 @@ -8780,7 +8780,7 @@ msgstr "" #. module: base #: model:res.country,name:base.jm msgid "Jamaica" -msgstr "" +msgstr "Jamaica" #. module: base #: model:ir.actions.act_window,help:base.action_partner_category_form @@ -8800,7 +8800,7 @@ msgstr "" #: code:addons/base/res/partner/partner.py:250 #, python-format msgid "Warning" -msgstr "" +msgstr "Advarsel!" #. module: base #: selection:base.language.install,lang:0 @@ -8840,7 +8840,7 @@ msgstr "" #. module: base #: model:res.country,name:base.rw msgid "Rwanda" -msgstr "" +msgstr "Rwanda" #. module: base #: view:ir.sequence:0 @@ -8865,7 +8865,7 @@ msgstr "" #. module: base #: model:res.country,name:base.sg msgid "Singapore" -msgstr "" +msgstr "Singapore" #. module: base #: selection:ir.actions.act_window,target:0 @@ -8895,7 +8895,7 @@ msgstr "" #: field:res.partner.address,country_id:0 #: field:res.partner.bank,country_id:0 msgid "Country" -msgstr "" +msgstr "Land" #. module: base #: field:ir.model.fields,complete_name:0 @@ -8918,12 +8918,12 @@ msgstr "" #. module: base #: field:res.partner.category,name:0 msgid "Category Name" -msgstr "" +msgstr "Kategori Navn" #. module: base #: model:res.partner.category,name:base.res_partner_category_15 msgid "IT sector" -msgstr "" +msgstr "IT sektor" #. module: base #: view:ir.actions.act_window:0 @@ -8975,7 +8975,7 @@ msgstr "" #: selection:ir.ui.view,type:0 #: selection:wizard.ir.model.menu.create.line,view_type:0 msgid "Graph" -msgstr "" +msgstr "Graf" #. module: base #: model:ir.model,name:base.model_ir_actions_server @@ -9017,7 +9017,7 @@ msgstr "" #. module: base #: model:ir.ui.menu,name:base.menu_localisation msgid "Localisation" -msgstr "" +msgstr "Lokalisering" #. module: base #: view:ir.actions.server:0 @@ -9070,7 +9070,7 @@ msgstr "" #. module: base #: field:ir.actions.server,mobile:0 msgid "Mobile No" -msgstr "" +msgstr "Mobil nr." #. module: base #: model:ir.actions.act_window,name:base.action_partner_by_category @@ -9084,7 +9084,7 @@ msgstr "" #. module: base #: view:base.module.upgrade:0 msgid "System Update" -msgstr "" +msgstr "Systemopdatering" #. module: base #: selection:ir.translation,type:0 @@ -9099,18 +9099,18 @@ msgstr "" #. module: base #: model:res.country,name:base.sc msgid "Seychelles" -msgstr "" +msgstr "Seychellerne" #. module: base #: model:ir.model,name:base.model_res_partner_bank #: view:res.partner.bank:0 msgid "Bank Accounts" -msgstr "" +msgstr "Bankkonti" #. module: base #: model:res.country,name:base.sl msgid "Sierra Leone" -msgstr "" +msgstr "Sierra Leone" #. module: base #: view:res.company:0 @@ -9126,7 +9126,7 @@ msgstr "" #. module: base #: field:res.partner.bank,owner_name:0 msgid "Account Owner" -msgstr "" +msgstr "Konto ejer" #. module: base #: code:addons/base/res/res_user.py:256 @@ -9155,7 +9155,7 @@ msgstr "" #: field:res.partner.address,function:0 #: selection:workflow.activity,kind:0 msgid "Function" -msgstr "" +msgstr "Funktion" #. module: base #: view:res.widget:0 @@ -9165,12 +9165,12 @@ msgstr "" #. module: base #: selection:ir.actions.todo,restart:0 msgid "Never" -msgstr "" +msgstr "Aldrig" #. module: base #: selection:res.partner.address,type:0 msgid "Delivery" -msgstr "" +msgstr "Levering" #. module: base #: model:res.partner.title,name:base.res_partner_title_pvt_ltd @@ -9197,7 +9197,7 @@ msgstr "" #. module: base #: model:res.country,name:base.kp msgid "North Korea" -msgstr "" +msgstr "Nordkorea" #. module: base #: selection:ir.actions.server,state:0 @@ -9240,7 +9240,7 @@ msgstr "" #. module: base #: model:res.country,name:base.lk msgid "Sri Lanka" -msgstr "" +msgstr "Sri Lanka" #. module: base #: selection:base.language.install,lang:0 diff --git a/openerp/addons/base/i18n/en_GB.po b/openerp/addons/base/i18n/en_GB.po index e9c4a7b1bc0..45a31676521 100644 --- a/openerp/addons/base/i18n/en_GB.po +++ b/openerp/addons/base/i18n/en_GB.po @@ -8,14 +8,14 @@ msgstr "" "Project-Id-Version: openobject-server\n" "Report-Msgid-Bugs-To: FULL NAME \n" "POT-Creation-Date: 2011-01-11 11:14+0000\n" -"PO-Revision-Date: 2011-07-28 15:35+0000\n" +"PO-Revision-Date: 2011-09-22 14:47+0000\n" "Last-Translator: John Bradshaw \n" "Language-Team: English (United Kingdom) \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-09-01 04:44+0000\n" -"X-Generator: Launchpad (build 13827)\n" +"X-Launchpad-Export-Date: 2011-09-23 04:38+0000\n" +"X-Generator: Launchpad (build 14012)\n" #. module: base #: view:ir.filters:0 @@ -1972,7 +1972,7 @@ msgstr "Iteration Actions" #. module: base #: help:multi_company.default,company_id:0 msgid "Company where the user is connected" -msgstr "" +msgstr "Company where the user is connected" #. module: base #: field:publisher_warranty.contract,date_stop:0 @@ -2583,7 +2583,7 @@ msgstr "Search Actions" #: model:ir.actions.act_window,name:base.action_view_partner_wizard_ean_check #: view:partner.wizard.ean.check:0 msgid "Ean check" -msgstr "" +msgstr "Ean check" #. module: base #: field:res.partner,vat:0 @@ -2623,7 +2623,7 @@ msgstr "GPL-2 or later version" #. module: base #: model:res.partner.title,shortcut:base.res_partner_title_sir msgid "M." -msgstr "" +msgstr "M." #. module: base #: code:addons/base/module/module.py:429 @@ -3001,7 +3001,7 @@ msgstr "License" #. module: base #: field:ir.attachment,url:0 msgid "Url" -msgstr "" +msgstr "Url" #. module: base #: selection:ir.actions.todo,restart:0 @@ -3153,7 +3153,7 @@ msgstr "Workflows" #. module: base #: field:ir.translation,xml_id:0 msgid "XML Id" -msgstr "" +msgstr "XML Id" #. module: base #: model:ir.actions.act_window,name:base.action_config_user_form @@ -3224,7 +3224,7 @@ msgstr "Abkhazian / аҧсуа" #. module: base #: view:base.module.configuration:0 msgid "System Configuration Done" -msgstr "" +msgstr "System Configuration Done" #. module: base #: code:addons/orm.py:929 @@ -3271,7 +3271,7 @@ msgstr "That contract is already registered in the system." #. module: base #: help:ir.sequence,suffix:0 msgid "Suffix value of the record for the sequence" -msgstr "" +msgstr "Suffix value of the record for the sequence" #. module: base #: selection:base.language.install,lang:0 @@ -3343,7 +3343,7 @@ msgstr "Installed" #. module: base #: selection:base.language.install,lang:0 msgid "Ukrainian / українська" -msgstr "" +msgstr "Ukrainian / українська" #. module: base #: model:ir.actions.act_window,name:base.action_translation @@ -3389,7 +3389,7 @@ msgstr "Next Number" #. module: base #: help:workflow.transition,condition:0 msgid "Expression to be satisfied if we want the transition done." -msgstr "" +msgstr "Expression to be satisfied if we want the transition done." #. module: base #: selection:base.language.install,lang:0 @@ -3518,6 +3518,12 @@ msgid "" "Would your payment have been carried out after this mail was sent, please " "consider the present one as void." msgstr "" +"Please note that the following payments are now due. If your payment " +" has been sent, kindly forward your payment details. If " +"payment will be delayed, please contact us to " +"discuss. \n" +"If payment was performed after this mail was sent, please consider the " +"present one as void." #. module: base #: model:res.country,name:base.mx @@ -3673,6 +3679,8 @@ msgid "" "If set to true, the action will not be displayed on the right toolbar of a " "form view" msgstr "" +"If set to true, the action will not be displayed on the right toolbar of a " +"form view" #. module: base #: model:res.country,name:base.ms @@ -3717,7 +3725,7 @@ msgstr "English (UK)" #. module: base #: selection:base.language.install,lang:0 msgid "Japanese / 日本語" -msgstr "" +msgstr "Japanese / 日本語" #. module: base #: help:workflow.transition,act_from:0 @@ -3725,6 +3733,8 @@ msgid "" "Source activity. When this activity is over, the condition is tested to " "determine if we can start the ACT_TO activity." msgstr "" +"Source activity. When this activity is over, the condition is tested to " +"determine if we can start the ACT_TO activity." #. module: base #: model:res.partner.category,name:base.res_partner_category_3 @@ -3885,7 +3895,7 @@ msgstr "Init Date" #. module: base #: selection:base.language.install,lang:0 msgid "Gujarati / ગુજરાતી" -msgstr "" +msgstr "Gujarati / ગુજરાતી" #. module: base #: code:addons/base/module/module.py:257 @@ -3953,6 +3963,9 @@ msgid "" "form, signal tests the name of the pressed button. If signal is NULL, no " "button is necessary to validate this transition." msgstr "" +"When the operation of transition comes from a button press in the client " +"form, signal tests the name of the pressed button. If signal is NULL, no " +"button is necessary to validate this transition." #. module: base #: help:multi_company.default,object_id:0 @@ -3972,7 +3985,7 @@ msgstr "Menu Name" #. module: base #: view:ir.module.module:0 msgid "Author Website" -msgstr "" +msgstr "Author Website" #. module: base #: view:ir.attachment:0 @@ -4012,6 +4025,8 @@ msgid "" "Whether values for this field can be translated (enables the translation " "mechanism for that field)" msgstr "" +"Whether values for this field can be translated (enables the translation " +"mechanism for that field)" #. module: base #: view:res.lang:0 @@ -4072,13 +4087,13 @@ msgstr "Price Accuracy" #. module: base #: selection:base.language.install,lang:0 msgid "Latvian / latviešu valoda" -msgstr "" +msgstr "Latvian / latviešu valoda" #. module: base #: view:res.config:0 #: view:res.config.installer:0 msgid "vsep" -msgstr "" +msgstr "vsep" #. module: base #: selection:base.language.install,lang:0 @@ -4099,7 +4114,7 @@ msgstr "Workitem" #. module: base #: view:ir.actions.todo:0 msgid "Set as Todo" -msgstr "" +msgstr "Set as Todo" #. module: base #: field:ir.actions.act_window.view,act_window_id:0 @@ -4177,7 +4192,7 @@ msgstr "Menus" #. module: base #: selection:base.language.install,lang:0 msgid "Serbian (Latin) / srpski" -msgstr "" +msgstr "Serbian (Latin) / srpski" #. module: base #: model:res.country,name:base.il @@ -4353,7 +4368,7 @@ msgstr "" #. module: base #: view:base.language.import:0 msgid "- module,type,name,res_id,src,value" -msgstr "" +msgstr "- module,type,name,res_id,src,value" #. module: base #: selection:base.language.install,lang:0 @@ -4372,7 +4387,7 @@ msgstr "" #. module: base #: help:ir.model.fields,relation:0 msgid "For relationship fields, the technical name of the target model" -msgstr "" +msgstr "For relationship fields, the technical name of the target model" #. module: base #: selection:base.language.install,lang:0 @@ -4387,7 +4402,7 @@ msgstr "Inherited View" #. module: base #: view:ir.translation:0 msgid "Source Term" -msgstr "" +msgstr "Source Term" #. module: base #: model:ir.ui.menu,name:base.menu_main_pm @@ -4397,7 +4412,7 @@ msgstr "Project" #. module: base #: field:ir.ui.menu,web_icon_hover_data:0 msgid "Web Icon Image (hover)" -msgstr "" +msgstr "Web Icon Image (hover)" #. module: base #: view:base.module.import:0 @@ -4417,7 +4432,7 @@ msgstr "Create User" #. module: base #: view:partner.clear.ids:0 msgid "Want to Clear Ids ? " -msgstr "" +msgstr "Want to Clear Ids ? " #. module: base #: field:publisher_warranty.contract,name:0 @@ -4469,17 +4484,17 @@ msgstr "Fed. State" #. module: base #: field:ir.actions.server,copy_object:0 msgid "Copy Of" -msgstr "" +msgstr "Copy Of" #. module: base #: field:ir.model,osv_memory:0 msgid "In-memory model" -msgstr "" +msgstr "In-memory model" #. module: base #: view:partner.clear.ids:0 msgid "Clear Ids" -msgstr "" +msgstr "Clear Ids" #. module: base #: model:res.country,name:base.io @@ -4501,7 +4516,7 @@ msgstr "Field Mapping" #. module: base #: view:publisher_warranty.contract:0 msgid "Refresh Validation Dates" -msgstr "" +msgstr "Refresh Validation Dates" #. module: base #: view:ir.model:0 @@ -4572,7 +4587,7 @@ msgstr "_Ok" #. module: base #: help:ir.filters,user_id:0 msgid "False means for every user" -msgstr "" +msgstr "False means for every user" #. module: base #: code:addons/base/module/module.py:198 @@ -4621,6 +4636,7 @@ msgstr "Contacts" msgid "" "Unable to delete this document because it is used as a default property" msgstr "" +"Unable to delete this document because it is used as a default property" #. module: base #: view:res.widget.wizard:0 @@ -4674,7 +4690,7 @@ msgstr "" #: code:addons/orm.py:1350 #, python-format msgid "Insufficient fields for Calendar View!" -msgstr "" +msgstr "Insufficient fields for Calendar View!" #. module: base #: selection:ir.property,type:0 @@ -4687,6 +4703,8 @@ msgid "" "The path to the main report file (depending on Report Type) or NULL if the " "content is in another data field" msgstr "" +"The path to the main report file (depending on Report Type) or NULL if the " +"content is in another data field" #. module: base #: help:res.config.users,company_id:0 @@ -4748,7 +4766,7 @@ msgstr "Close" #. module: base #: selection:base.language.install,lang:0 msgid "Spanish (MX) / Español (MX)" -msgstr "" +msgstr "Spanish (MX) / Español (MX)" #. module: base #: view:res.log:0 @@ -4783,7 +4801,7 @@ msgstr "Publisher Warranty Contracts" #. module: base #: help:res.log,name:0 msgid "The logging message." -msgstr "" +msgstr "The logging message." #. module: base #: field:base.language.export,format:0 @@ -5018,7 +5036,7 @@ msgstr "" #. module: base #: help:ir.cron,interval_number:0 msgid "Repeat every x." -msgstr "" +msgstr "Repeat every x." #. module: base #: wizard_view:server.action.create,step_1:0 @@ -5078,6 +5096,8 @@ msgid "" "If specified, this action will be opened at logon for this user, in addition " "to the standard menu." msgstr "" +"If specified, this action will be opened at logon for this user, in addition " +"to the standard menu." #. module: base #: view:ir.values:0 @@ -5088,7 +5108,7 @@ msgstr "Client Actions" #: code:addons/orm.py:1806 #, python-format msgid "The exists method is not implemented on this object !" -msgstr "" +msgstr "The exists method is not implemented on this object !" #. module: base #: code:addons/base/module/module.py:336 @@ -5113,7 +5133,7 @@ msgstr "Connect Events to Actions" #. module: base #: model:ir.model,name:base.model_base_update_translations msgid "base.update.translations" -msgstr "" +msgstr "base.update.translations" #. module: base #: field:ir.module.category,parent_id:0 @@ -5124,7 +5144,7 @@ msgstr "Parent Category" #. module: base #: selection:ir.property,type:0 msgid "Integer Big" -msgstr "" +msgstr "Integer Big" #. module: base #: selection:res.partner.address,type:0 @@ -5158,7 +5178,7 @@ msgstr "Communication" #. module: base #: view:ir.actions.report.xml:0 msgid "RML Report" -msgstr "" +msgstr "RML Report" #. module: base #: model:ir.model,name:base.model_ir_server_object_lines @@ -5206,7 +5226,7 @@ msgstr "Nigeria" #: code:addons/base/ir/ir_model.py:250 #, python-format msgid "For selection fields, the Selection Options must be given!" -msgstr "" +msgstr "For selection fields, the Selection Options must be given!" #. module: base #: model:ir.actions.act_window,name:base.action_partner_sms_send @@ -5254,6 +5274,13 @@ msgid "" "installed the CRM, with the history tab, you can track all the interactions " "with a partner such as opportunities, emails, or sales orders issued." msgstr "" +"Customers (also called Partners in other areas of the system) helps you " +"manage your address book of companies whether they are prospects, customers " +"and/or suppliers. The partner form allows you to track and record all the " +"necessary information to interact with your partners from the company " +"address to their contacts as well as pricelists, and much more. If you " +"installed the CRM, with the history tab, you can track all interactions with " +"a partner such as opportunities, emails, or sales orders issued." #. module: base #: model:res.country,name:base.ph @@ -5278,7 +5305,7 @@ msgstr "Content" #. module: base #: help:ir.rule,global:0 msgid "If no group is specified the rule is global and applied to everyone" -msgstr "" +msgstr "If no group is specified the rule is global and applied to everyone" #. module: base #: model:res.country,name:base.td @@ -5355,6 +5382,9 @@ msgid "" "groups. If this field is empty, OpenERP will compute visibility based on the " "related object's read access." msgstr "" +"If you have groups, the visibility of this menu will be based on these " +"groups. If this field is empty, OpenERP will compute visibility based on the " +"related object's read access." #. module: base #: model:ir.actions.act_window,name:base.action_ui_view_custom @@ -5496,7 +5526,7 @@ msgstr "Spanish (EC) / Español (EC)" #. module: base #: help:ir.ui.view,xml_id:0 msgid "ID of the view defined in xml file" -msgstr "" +msgstr "ID of the view defined in xml file" #. module: base #: model:ir.model,name:base.model_base_module_import @@ -5512,7 +5542,7 @@ msgstr "American Samoa" #. module: base #: help:ir.actions.act_window,res_model:0 msgid "Model name of the object to open in the view window" -msgstr "" +msgstr "Model name of the object to open in the view window" #. module: base #: field:res.log,secondary:0 @@ -5692,11 +5722,15 @@ msgid "" "Warning: if \"email_from\" and \"smtp_server\" aren't configured, it won't " "be possible to email new users." msgstr "" +"If an email is provided, the user will be sent a message welcoming them.\n" +"\n" +"Warning: if \"email_from\" and \"smtp_server\" aren't configured, it won't " +"be possible to email new users." #. module: base #: selection:base.language.install,lang:0 msgid "Flemish (BE) / Vlaams (BE)" -msgstr "" +msgstr "Flemish (BE) / Vlaams (BE)" #. module: base #: field:ir.cron,interval_number:0 @@ -5746,7 +5780,7 @@ msgstr "ir.actions.todo" #: code:addons/base/res/res_config.py:94 #, python-format msgid "Couldn't find previous ir.actions.todo" -msgstr "" +msgstr "Couldn't find previous ir.actions.todo" #. module: base #: view:ir.actions.act_window:0 @@ -5761,7 +5795,7 @@ msgstr "Custom Shortcuts" #. module: base #: selection:base.language.install,lang:0 msgid "Vietnamese / Tiếng Việt" -msgstr "" +msgstr "Vietnamese / Tiếng Việt" #. module: base #: model:res.country,name:base.dz @@ -5776,7 +5810,7 @@ msgstr "Belgium" #. module: base #: model:ir.model,name:base.model_osv_memory_autovacuum msgid "osv_memory.autovacuum" -msgstr "" +msgstr "osv_memory.autovacuum" #. module: base #: field:base.language.export,lang:0 @@ -5809,30 +5843,30 @@ msgstr "Companies" #. module: base #: view:res.lang:0 msgid "%H - Hour (24-hour clock) [00,23]." -msgstr "" +msgstr "%H - Hour (24-hour clock) [00,23]." #. module: base #: model:ir.model,name:base.model_res_widget msgid "res.widget" -msgstr "" +msgstr "res.widget" #. module: base #: code:addons/base/ir/ir_model.py:258 #, python-format msgid "Model %s does not exist!" -msgstr "" +msgstr "Model %s does not exist!" #. module: base #: code:addons/base/res/res_lang.py:159 #, python-format msgid "You cannot delete the language which is User's Preferred Language !" -msgstr "" +msgstr "You cannot delete the language which is User's Preferred Language !" #. module: base #: code:addons/fields.py:103 #, python-format msgid "Not implemented get_memory method !" -msgstr "" +msgstr "Not implemented get_memory method !" #. module: base #: view:ir.actions.server:0 @@ -5879,7 +5913,7 @@ msgstr "Neutral Zone" #. module: base #: selection:base.language.install,lang:0 msgid "Hindi / हिंदी" -msgstr "" +msgstr "Hindi / हिंदी" #. module: base #: view:ir.model:0 @@ -5926,7 +5960,7 @@ msgstr "Window Actions" #. module: base #: view:res.lang:0 msgid "%I - Hour (12-hour clock) [01,12]." -msgstr "" +msgstr "%I - Hour (12-hour clock) [01,12]." #. module: base #: selection:publisher_warranty.contract.wizard,state:0 @@ -5964,12 +5998,14 @@ msgid "" "View type: set to 'tree' for a hierarchical tree view, or 'form' for other " "views" msgstr "" +"View type: set to 'tree' for a hierarchical tree view, or 'form' for other " +"views" #. module: base #: code:addons/base/res/res_config.py:421 #, python-format msgid "Click 'Continue' to configure the next addon..." -msgstr "" +msgstr "Click 'Continue' to configure the next addon..." #. module: base #: field:ir.actions.server,record_id:0 @@ -6010,7 +6046,7 @@ msgstr "" #: code:addons/base/ir/ir_actions.py:629 #, python-format msgid "Please specify server option --email-from !" -msgstr "" +msgstr "Please specify server option --email-from !" #. module: base #: field:base.language.import,name:0 @@ -6070,6 +6106,7 @@ msgid "" "It gives the status if the tip has to be displayed or not when a user " "executes an action" msgstr "" +"It shows if the tip is to be displayed or not when a user executes an action" #. module: base #: view:ir.model:0 @@ -6126,7 +6163,7 @@ msgstr "Code" #. module: base #: model:ir.model,name:base.model_res_config_installer msgid "res.config.installer" -msgstr "" +msgstr "res.config.installer" #. module: base #: model:res.country,name:base.mc @@ -6170,7 +6207,7 @@ msgstr "Sequence Codes" #. module: base #: selection:base.language.install,lang:0 msgid "Spanish (CO) / Español (CO)" -msgstr "" +msgstr "Spanish (CO) / Español (CO)" #. module: base #: view:base.module.configuration:0 @@ -6178,6 +6215,8 @@ msgid "" "All pending configuration wizards have been executed. You may restart " "individual wizards via the list of configuration wizards." msgstr "" +"All pending configuration wizards have been executed. You may restart " +"individual wizards via the list of configuration wizards." #. module: base #: wizard_button:server.action.create,step_1,create:0 @@ -6187,7 +6226,7 @@ msgstr "Create" #. module: base #: view:ir.sequence:0 msgid "Current Year with Century: %(year)s" -msgstr "" +msgstr "Current Year with Century: %(year)s" #. module: base #: field:ir.exports,export_fields:0 @@ -6202,13 +6241,13 @@ msgstr "France" #. module: base #: model:ir.model,name:base.model_res_log msgid "res.log" -msgstr "" +msgstr "res.log" #. module: base #: help:ir.translation,module:0 #: help:ir.translation,xml_id:0 msgid "Maps to the ir_model_data for which this translation is provided." -msgstr "" +msgstr "Maps to the ir_model_data for which this translation is provided." #. module: base #: view:workflow.activity:0 @@ -6302,7 +6341,7 @@ msgstr "Todo" #. module: base #: field:ir.attachment,datas:0 msgid "File Content" -msgstr "" +msgstr "File Content" #. module: base #: model:res.country,name:base.pa @@ -6319,12 +6358,13 @@ msgstr "Ltd" msgid "" "The group that a user must have to be authorized to validate this transition." msgstr "" +"The group that a user must have to be authorized to validate this transition." #. module: base #: constraint:res.config.users:0 #: constraint:res.users:0 msgid "The chosen company is not in the allowed companies for this user" -msgstr "" +msgstr "The chosen company is not in the allowed companies for this user" #. module: base #: model:res.country,name:base.gi @@ -6346,6 +6386,7 @@ msgstr "Pitcairn Island" msgid "" "We suggest to reload the menu tab to see the new menus (Ctrl+T then Ctrl+R)." msgstr "" +"We suggest reloading the menu tab to see the new menus (Ctrl+T then Ctrl+R)." #. module: base #: model:ir.actions.act_window,name:base.action_rule @@ -6398,7 +6439,7 @@ msgstr "Search View" #. module: base #: sql_constraint:res.lang:0 msgid "The code of the language must be unique !" -msgstr "" +msgstr "The code of the language must be unique !" #. module: base #: model:ir.actions.act_window,name:base.action_attachment @@ -6441,7 +6482,7 @@ msgstr "Write Access" #. module: base #: view:res.lang:0 msgid "%m - Month number [01,12]." -msgstr "" +msgstr "%m - Month number [01,12]." #. module: base #: field:res.bank,city:0 @@ -6499,7 +6540,7 @@ msgstr "English (US)" #: view:ir.model.data:0 #: model:ir.ui.menu,name:base.ir_model_data_menu msgid "Object Identifiers" -msgstr "" +msgstr "Object Identifiers" #. module: base #: model:ir.actions.act_window,help:base.action_partner_title_partner @@ -6507,11 +6548,13 @@ msgid "" "Manage the partner titles you want to have available in your system. The " "partner titles is the legal status of the company: Private Limited, SA, etc." msgstr "" +"Manage the partner titles you want to have available in your system. The " +"partner title is the legal status of the company: Private Limited, SA, etc." #. module: base #: view:base.language.export:0 msgid "To browse official translations, you can start with these links:" -msgstr "" +msgstr "To browse official translations, you can start with these links:" #. module: base #: code:addons/base/ir/ir_model.py:484 @@ -6520,6 +6563,8 @@ msgid "" "You can not read this document (%s) ! Be sure your user belongs to one of " "these groups: %s." msgstr "" +"You can not read this document (%s) ! Be sure your user belongs to one of " +"these groups: %s." #. module: base #: view:res.bank:0 @@ -6538,7 +6583,7 @@ msgstr "Installed version" #. module: base #: selection:base.language.install,lang:0 msgid "Mongolian / монгол" -msgstr "" +msgstr "Mongolian / монгол" #. module: base #: model:res.country,name:base.mr @@ -6553,7 +6598,7 @@ msgstr "ir.translation" #. module: base #: view:base.module.update:0 msgid "Module update result" -msgstr "" +msgstr "Module update result" #. module: base #: view:workflow.activity:0 @@ -6575,7 +6620,7 @@ msgstr "Parent Company" #. module: base #: selection:base.language.install,lang:0 msgid "Spanish (CR) / Español (CR)" -msgstr "" +msgstr "Spanish (CR) / Español (CR)" #. module: base #: field:res.currency.rate,rate:0 @@ -6615,6 +6660,9 @@ msgid "" "for the currency: %s \n" "at the date: %s" msgstr "" +"No rate found \n" +"for the currency: %s \n" +"at the date: %s" #. module: base #: model:ir.actions.act_window,help:base.action_ui_view_custom @@ -6622,6 +6670,8 @@ msgid "" "Customized views are used when users reorganize the content of their " "dashboard views (via web client)" msgstr "" +"Customised views are used when users reorganise the content of their " +"dashboard views (via web client)" #. module: base #: field:ir.model,name:0 @@ -6660,7 +6710,7 @@ msgstr "Icon" #. module: base #: help:ir.model.fields,model_id:0 msgid "The model this field belongs to" -msgstr "" +msgstr "The model this field belongs to" #. module: base #: model:res.country,name:base.mq @@ -6670,7 +6720,7 @@ msgstr "Martinique (French)" #. module: base #: view:ir.sequence.type:0 msgid "Sequences Type" -msgstr "" +msgstr "Sequences Type" #. module: base #: model:ir.actions.act_window,name:base.res_request-act @@ -6694,7 +6744,7 @@ msgstr "Or" #: model:ir.actions.act_window,name:base.res_log_act_window #: model:ir.ui.menu,name:base.menu_res_log_act_window msgid "Client Logs" -msgstr "" +msgstr "Client Logs" #. module: base #: model:res.country,name:base.al @@ -6713,6 +6763,8 @@ msgid "" "You cannot delete the language which is Active !\n" "Please de-activate the language first." msgstr "" +"You cannot delete a language which is active !\n" +"Please de-activate the language first." #. module: base #: view:base.language.install:0 @@ -6721,6 +6773,8 @@ msgid "" "Please be patient, this operation may take a few minutes (depending on the " "number of modules currently installed)..." msgstr "" +"Please be patient, this operation may take a few minutes (depending on the " +"number of modules currently installed)..." #. module: base #: field:ir.ui.menu,child_id:0 @@ -6739,18 +6793,18 @@ msgstr "Problem in configuration `Record Id` in Server Action!" #: code:addons/orm.py:2316 #, python-format msgid "ValidateError" -msgstr "" +msgstr "ValidateError" #. module: base #: view:base.module.import:0 #: view:base.module.update:0 msgid "Open Modules" -msgstr "" +msgstr "Open Modules" #. module: base #: model:ir.actions.act_window,help:base.action_res_bank_form msgid "Manage bank records you want to be used in the system." -msgstr "" +msgstr "Manage bank records you want to be used in the system." #. module: base #: view:base.module.import:0 @@ -6768,6 +6822,8 @@ msgid "" "The path to the main report file (depending on Report Type) or NULL if the " "content is in another field" msgstr "" +"The path to the main report file (depending on Report Type) or NULL if the " +"content is in another field" #. module: base #: model:res.country,name:base.la @@ -6794,6 +6850,8 @@ msgid "" "The sum of the data (2nd field) is null.\n" "We can't draw a pie chart !" msgstr "" +"The sum of the data (2nd field) is null.\n" +"We can't draw a pie chart !" #. module: base #: model:ir.ui.menu,name:base.menu_lunch_reporting @@ -6815,7 +6873,7 @@ msgstr "Togo" #. module: base #: selection:ir.module.module,license:0 msgid "Other Proprietary" -msgstr "" +msgstr "Other Proprietary" #. module: base #: selection:workflow.activity,kind:0 @@ -6826,7 +6884,7 @@ msgstr "Stop All" #: code:addons/orm.py:412 #, python-format msgid "The read_group method is not implemented on this object !" -msgstr "" +msgstr "The read_group method is not implemented on this object !" #. module: base #: view:ir.model.data:0 @@ -6846,7 +6904,7 @@ msgstr "Cascade" #. module: base #: field:workflow.transition,group_id:0 msgid "Group Required" -msgstr "" +msgstr "Group Required" #. module: base #: view:ir.actions.configuration.wizard:0 @@ -6869,17 +6927,19 @@ msgid "" "Enable this if you want to execute missed occurences as soon as the server " "restarts." msgstr "" +"Enable this if you want to execute missed occurences as soon as the server " +"restarts." #. module: base #: view:base.module.upgrade:0 msgid "Start update" -msgstr "" +msgstr "Start update" #. module: base #: code:addons/base/publisher_warranty/publisher_warranty.py:144 #, python-format msgid "Contract validation error" -msgstr "" +msgstr "Contract validation error" #. module: base #: field:res.country.state,name:0 @@ -6906,7 +6966,7 @@ msgstr "ir.actions.report.xml" #. module: base #: model:res.partner.title,shortcut:base.res_partner_title_miss msgid "Mss" -msgstr "" +msgstr "Mss" #. module: base #: model:ir.model,name:base.model_ir_ui_view @@ -6916,7 +6976,7 @@ msgstr "ir.ui.view" #. module: base #: constraint:res.partner:0 msgid "Error ! You can not create recursive associated members." -msgstr "" +msgstr "Error ! You can not create recursive associated members." #. module: base #: help:res.lang,code:0 @@ -6931,7 +6991,7 @@ msgstr "OpenERP Partners" #. module: base #: model:ir.ui.menu,name:base.menu_hr_manager msgid "HR Manager Dashboard" -msgstr "" +msgstr "HR Manager Dashboard" #. module: base #: code:addons/base/module/module.py:253 @@ -6939,11 +6999,12 @@ msgstr "" msgid "" "Unable to install module \"%s\" because an external dependency is not met: %s" msgstr "" +"Unable to install module \"%s\" because an external dependency is not met: %s" #. module: base #: view:ir.module.module:0 msgid "Search modules" -msgstr "" +msgstr "Search modules" #. module: base #: model:res.country,name:base.by @@ -6968,6 +7029,10 @@ msgid "" "not connect to the system. You can assign them groups in order to give them " "specific access to the applications they need to use in the system." msgstr "" +"Create and manage users that will connect to the system. Users can be " +"deactivated should there be a period of time during which they will/should " +"not connect to the system. You can assign them groups to give them specific " +"access to the applications they need to use." #. module: base #: selection:res.request,priority:0 @@ -6983,13 +7048,13 @@ msgstr "Street2" #. module: base #: model:ir.actions.act_window,name:base.action_view_base_module_update msgid "Module Update" -msgstr "" +msgstr "Module Update" #. module: base #: code:addons/base/module/wizard/base_module_upgrade.py:95 #, python-format msgid "Following modules are not installed or unknown: %s" -msgstr "" +msgstr "Following modules are not installed or unknown: %s" #. module: base #: view:ir.cron:0 @@ -7018,7 +7083,7 @@ msgstr "Open Window" #. module: base #: field:ir.actions.act_window,auto_search:0 msgid "Auto Search" -msgstr "" +msgstr "Auto Search" #. module: base #: field:ir.actions.act_window,filter:0 @@ -7064,25 +7129,25 @@ msgstr "Load" #: help:res.config.users,name:0 #: help:res.users,name:0 msgid "The new user's real name, used for searching and most listings" -msgstr "" +msgstr "The new user's real name, used for searching and most listings" #. module: base #: code:addons/osv.py:154 #: code:addons/osv.py:156 #, python-format msgid "Integrity Error" -msgstr "" +msgstr "Integrity Error" #. module: base #: model:ir.model,name:base.model_ir_wizard_screen msgid "ir.wizard.screen" -msgstr "" +msgstr "ir.wizard.screen" #. module: base #: code:addons/base/ir/ir_model.py:223 #, python-format msgid "Size of the field can never be less than 1 !" -msgstr "" +msgstr "Size of the field can never be less than 1 !" #. module: base #: model:res.country,name:base.so @@ -7092,7 +7157,7 @@ msgstr "Somalia" #. module: base #: selection:publisher_warranty.contract,state:0 msgid "Terminated" -msgstr "" +msgstr "Terminated" #. module: base #: model:res.partner.category,name:base.res_partner_category_13 @@ -7102,7 +7167,7 @@ msgstr "Important customers" #. module: base #: view:res.lang:0 msgid "Update Terms" -msgstr "" +msgstr "Update Terms" #. module: base #: field:partner.sms.send,mobile_to:0 @@ -7121,7 +7186,7 @@ msgstr "Arguments" #: code:addons/orm.py:716 #, python-format msgid "Database ID doesn't exist: %s : %s" -msgstr "" +msgstr "Database ID doesn't exist: %s : %s" #. module: base #: selection:ir.module.module,license:0 @@ -7137,7 +7202,7 @@ msgstr "GPL Version 3" #: code:addons/orm.py:836 #, python-format msgid "key '%s' not found in selection field '%s'" -msgstr "" +msgstr "key '%s' not found in selection field '%s'" #. module: base #: view:partner.wizard.ean.check:0 @@ -7148,7 +7213,7 @@ msgstr "Correct EAN13" #: code:addons/orm.py:2317 #, python-format msgid "The value \"%s\" for the field \"%s\" is not in the selection" -msgstr "" +msgstr "The value \"%s\" for the field \"%s\" is not in the selection" #. module: base #: field:res.partner,customer:0 diff --git a/openerp/addons/base/i18n/kk.po b/openerp/addons/base/i18n/kk.po new file mode 100644 index 00000000000..1df9844334b --- /dev/null +++ b/openerp/addons/base/i18n/kk.po @@ -0,0 +1,9248 @@ +# Kazakh translation for openobject-server +# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011 +# This file is distributed under the same license as the openobject-server package. +# FIRST AUTHOR , 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-server\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2011-01-11 11:14+0000\n" +"PO-Revision-Date: 2011-09-16 07:28+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Kazakh \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2011-09-17 04:54+0000\n" +"X-Generator: Launchpad (build 13955)\n" + +#. module: base +#: view:ir.filters:0 +#: field:ir.model.fields,domain:0 +#: field:ir.rule,domain:0 +#: field:ir.rule,domain_force:0 +#: field:res.partner.title,domain:0 +msgid "Domain" +msgstr "Домен" + +#. module: base +#: model:res.country,name:base.sh +msgid "Saint Helena" +msgstr "Әулие Елена ар." + +#. module: base +#: view:ir.actions.report.xml:0 +msgid "Other Configuration" +msgstr "" + +#. module: base +#: selection:ir.property,type:0 +msgid "DateTime" +msgstr "Күн мен уақыт" + +#. module: base +#: code:addons/fields.py:534 +#, python-format +msgid "" +"The second argument of the many2many field %s must be a SQL table !You used " +"%s, which is not a valid SQL table name." +msgstr "" + +#. module: base +#: view:ir.values:0 +#: field:ir.values,meta_unpickle:0 +msgid "Metadata" +msgstr "Метаақпарат" + +#. module: base +#: field:ir.ui.view,arch:0 +#: field:ir.ui.view.custom,arch:0 +msgid "View Architecture" +msgstr "" + +#. module: base +#: field:base.language.import,code:0 +msgid "Code (eg:en__US)" +msgstr "" + +#. module: base +#: view:workflow:0 +#: view:workflow.activity:0 +#: field:workflow.activity,wkf_id:0 +#: field:workflow.instance,wkf_id:0 +#: field:workflow.transition,wkf_id:0 +#: field:workflow.workitem,wkf_id:0 +msgid "Workflow" +msgstr "" + +#. module: base +#: view:partner.sms.send:0 +msgid "SMS - Gateway: clickatell" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Hungarian / Magyar" +msgstr "" + +#. module: base +#: selection:ir.model.fields,select_level:0 +msgid "Not Searchable" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Spanish (VE) / Español (VE)" +msgstr "" + +#. module: base +#: field:ir.actions.server,wkf_model_id:0 +msgid "Workflow On" +msgstr "" + +#. module: base +#: field:ir.actions.act_window,display_menu_tip:0 +msgid "Display Menu Tips" +msgstr "" + +#. module: base +#: view:ir.module.module:0 +msgid "Created Views" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_model.py:485 +#, python-format +msgid "" +"You can not write in this document (%s) ! Be sure your user belongs to one " +"of these groups: %s." +msgstr "" + +#. module: base +#: help:ir.model.fields,domain:0 +msgid "" +"The optional domain to restrict possible values for relationship fields, " +"specified as a Python expression defining a list of triplets. For example: " +"[('color','=','red')]" +msgstr "" + +#. module: base +#: field:res.partner,ref:0 +msgid "Reference" +msgstr "Сілтеме" + +#. module: base +#: field:ir.actions.act_window,target:0 +msgid "Target Window" +msgstr "" + +#. module: base +#: code:addons/base/res/res_user.py:507 +#, python-format +msgid "Warning!" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_model.py:304 +#, python-format +msgid "" +"Properties of base fields cannot be altered in this manner! Please modify " +"them through Python code, preferably through a custom addon!" +msgstr "" + +#. module: base +#: code:addons/osv.py:133 +#, python-format +msgid "Constraint Error" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_ui_view_custom +msgid "ir.ui.view.custom" +msgstr "" + +#. module: base +#: model:res.country,name:base.sz +msgid "Swaziland" +msgstr "Свазиленд" + +#. module: base +#: code:addons/orm.py:1993 +#: code:addons/orm.py:3653 +#, python-format +msgid "created." +msgstr "" + +#. module: base +#: model:res.partner.category,name:base.res_partner_category_woodsuppliers0 +msgid "Wood Suppliers" +msgstr "" + +#. module: base +#: code:addons/base/module/module.py:303 +#, python-format +msgid "" +"Some installed modules depend on the module you plan to Uninstall :\n" +" %s" +msgstr "" + +#. module: base +#: field:ir.sequence,number_increment:0 +msgid "Increment Number" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_res_company_tree +#: model:ir.ui.menu,name:base.menu_action_res_company_tree +msgid "Company's Structure" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Inuktitut / ᐃᓄᒃᑎᑐᑦ" +msgstr "" + +#. module: base +#: view:res.partner:0 +msgid "Search Partner" +msgstr "" + +#. module: base +#: code:addons/base/res/res_user.py:132 +#, python-format +msgid "\"smtp_server\" needs to be set to send mails to users" +msgstr "" + +#. module: base +#: code:addons/base/module/wizard/base_export_language.py:60 +#, python-format +msgid "new" +msgstr "жаңа" + +#. module: base +#: field:ir.actions.report.xml,multi:0 +msgid "On multiple doc." +msgstr "" + +#. module: base +#: field:ir.module.category,module_nr:0 +msgid "Number of Modules" +msgstr "" + +#. module: base +#: help:multi_company.default,company_dest_id:0 +msgid "Company to store the current record" +msgstr "" + +#. module: base +#: field:res.partner.bank.type.field,size:0 +msgid "Max. Size" +msgstr "" + +#. module: base +#: field:res.partner.address,name:0 +msgid "Contact Name" +msgstr "Контакт атауы" + +#. module: base +#: code:addons/base/module/wizard/base_export_language.py:56 +#, python-format +msgid "" +"Save this document to a %s file and edit it with a specific software or a " +"text editor. The file encoding is UTF-8." +msgstr "" + +#. module: base +#: sql_constraint:res.lang:0 +msgid "The name of the language must be unique !" +msgstr "" + +#. module: base +#: selection:res.request,state:0 +msgid "active" +msgstr "белсенді" + +#. module: base +#: field:ir.actions.wizard,wiz_name:0 +msgid "Wizard Name" +msgstr "" + +#. module: base +#: code:addons/orm.py:2160 +#, python-format +msgid "Invalid group_by" +msgstr "" + +#. module: base +#: field:res.partner,credit_limit:0 +msgid "Credit Limit" +msgstr "" + +#. module: base +#: field:ir.model.data,date_update:0 +msgid "Update Date" +msgstr "" + +#. module: base +#: view:ir.attachment:0 +msgid "Owner" +msgstr "Иесі" + +#. module: base +#: field:ir.actions.act_window,src_model:0 +msgid "Source Object" +msgstr "" + +#. module: base +#: view:ir.actions.todo:0 +msgid "Config Wizard Steps" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_ui_view_sc +msgid "ir.ui.view_sc" +msgstr "" + +#. module: base +#: field:res.widget.user,widget_id:0 +#: field:res.widget.wizard,widgets_list:0 +msgid "Widget" +msgstr "" + +#. module: base +#: view:ir.model.access:0 +#: field:ir.model.access,group_id:0 +#: view:res.config.users:0 +msgid "Group" +msgstr "Тобы" + +#. module: base +#: field:ir.exports.line,name:0 +#: field:ir.translation,name:0 +#: field:res.partner.bank.type.field,name:0 +msgid "Field Name" +msgstr "" + +#. module: base +#: wizard_view:server.action.create,init:0 +#: wizard_field:server.action.create,init,type:0 +msgid "Select Action Type" +msgstr "" + +#. module: base +#: model:res.country,name:base.tv +msgid "Tuvalu" +msgstr "Тувалу" + +#. module: base +#: selection:ir.model,state:0 +msgid "Custom Object" +msgstr "" + +#. module: base +#: field:res.lang,date_format:0 +msgid "Date Format" +msgstr "Уақыт таңба пшімі" + +#. module: base +#: field:res.bank,email:0 +#: field:res.partner.address,email:0 +msgid "E-Mail" +msgstr "Эл.поштасы" + +#. module: base +#: model:res.country,name:base.an +msgid "Netherlands Antilles" +msgstr "Нидерландияның Антиль аралдары" + +#. module: base +#: code:addons/base/res/res_user.py:389 +#, python-format +msgid "" +"You can not remove the admin user as it is used internally for resources " +"created by OpenERP (updates, module installation, ...)" +msgstr "" + +#. module: base +#: model:res.country,name:base.gf +msgid "French Guyana" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Greek / Ελληνικά" +msgstr "Греция" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Bosnian / bosanski jezik" +msgstr "" + +#. module: base +#: help:ir.actions.report.xml,attachment_use:0 +msgid "" +"If you check this, then the second time the user prints with same attachment " +"name, it returns the previous report." +msgstr "" + +#. module: base +#: code:addons/orm.py:904 +#, python-format +msgid "The read method is not implemented on this object !" +msgstr "" + +#. module: base +#: help:res.lang,iso_code:0 +msgid "This ISO code is the name of po files to use for translations" +msgstr "" + +#. module: base +#: view:base.module.upgrade:0 +msgid "Your system will be updated." +msgstr "" + +#. module: base +#: field:ir.actions.todo,note:0 +#: selection:ir.property,type:0 +msgid "Text" +msgstr "Мәтін" + +#. module: base +#: field:res.country,name:0 +msgid "Country Name" +msgstr "" + +#. module: base +#: model:res.country,name:base.co +msgid "Colombia" +msgstr "Колумбия" + +#. module: base +#: view:ir.module.module:0 +msgid "Schedule Upgrade" +msgstr "" + +#. module: base +#: code:addons/orm.py:838 +#, python-format +msgid "Key/value '%s' not found in selection field '%s'" +msgstr "" + +#. module: base +#: help:res.country,code:0 +msgid "" +"The ISO country code in two chars.\n" +"You can use this field for quick search." +msgstr "" + +#. module: base +#: model:res.country,name:base.pw +msgid "Palau" +msgstr "Палау" + +#. module: base +#: view:res.partner:0 +msgid "Sales & Purchases" +msgstr "" + +#. module: base +#: view:ir.translation:0 +msgid "Untranslated" +msgstr "Аударылмаған" + +#. module: base +#: help:ir.actions.act_window,context:0 +msgid "" +"Context dictionary as Python expression, empty by default (Default: {})" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.ir_action_wizard +#: view:ir.actions.wizard:0 +#: model:ir.ui.menu,name:base.menu_ir_action_wizard +msgid "Wizards" +msgstr "" + +#. module: base +#: model:res.partner.category,name:base.res_partner_category_miscellaneoussuppliers0 +msgid "Miscellaneous Suppliers" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_model.py:255 +#, python-format +msgid "Custom fields must have a name that starts with 'x_' !" +msgstr "" + +#. module: base +#: help:ir.actions.server,action_id:0 +msgid "Select the Action Window, Report, Wizard to be executed." +msgstr "" + +#. module: base +#: view:res.config.users:0 +msgid "New User" +msgstr "" + +#. module: base +#: view:base.language.export:0 +msgid "Export done" +msgstr "" + +#. module: base +#: view:ir.model:0 +msgid "Model Description" +msgstr "" + +#. module: base +#: help:ir.actions.act_window,src_model:0 +msgid "" +"Optional model name of the objects on which this action should be visible" +msgstr "" + +#. module: base +#: field:workflow.transition,trigger_expr_id:0 +msgid "Trigger Expression" +msgstr "" + +#. module: base +#: model:res.country,name:base.jo +msgid "Jordan" +msgstr "Хордан" + +#. module: base +#: view:ir.module.module:0 +msgid "Certified" +msgstr "" + +#. module: base +#: model:res.country,name:base.er +msgid "Eritrea" +msgstr "Эритрея" + +#. module: base +#: view:res.config:0 +#: view:res.config.installer:0 +msgid "description" +msgstr "сипаттамасы" + +#. module: base +#: model:ir.ui.menu,name:base.menu_base_action_rule +msgid "Automated Actions" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_actions_actions +msgid "ir.actions.actions" +msgstr "" + +#. module: base +#: view:partner.wizard.ean.check:0 +msgid "Want to check Ean ? " +msgstr "" + +#. module: base +#: field:ir.values,key2:0 +msgid "Event Type" +msgstr "Оқиға түрі" + +#. module: base +#: view:base.language.export:0 +msgid "" +"OpenERP translations (core, modules, clients) are managed through " +"Launchpad.net, our open source project management facility. We use their " +"online interface to synchronize all translations efforts." +msgstr "" + +#. module: base +#: field:res.partner,title:0 +msgid "Partner Form" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Swedish / svenska" +msgstr "" + +#. module: base +#: model:res.country,name:base.rs +msgid "Serbia" +msgstr "Сербия" + +#. module: base +#: selection:ir.translation,type:0 +msgid "Wizard View" +msgstr "" + +#. module: base +#: model:res.country,name:base.kh +msgid "Cambodia, Kingdom of" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.ir_sequence_form +#: view:ir.sequence:0 +#: model:ir.ui.menu,name:base.menu_ir_sequence_form +#: model:ir.ui.menu,name:base.next_id_5 +msgid "Sequences" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_base_language_import +msgid "Language Import" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_config_users +msgid "res.config.users" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Albanian / Shqip" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_crm_config_opportunity +msgid "Opportunities" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_base_language_export +msgid "base.language.export" +msgstr "" + +#. module: base +#: model:res.country,name:base.pg +msgid "Papua New Guinea" +msgstr "Папуа - Жаңа Гвинея" + +#. module: base +#: help:ir.actions.report.xml,report_type:0 +msgid "Report Type, e.g. pdf, html, raw, sxw, odt, html2html, mako2html, ..." +msgstr "" + +#. module: base +#: model:res.partner.category,name:base.res_partner_category_4 +msgid "Basic Partner" +msgstr "" + +#. module: base +#: report:ir.module.reference.graph:0 +msgid "," +msgstr "" + +#. module: base +#: view:res.partner:0 +msgid "My Partners" +msgstr "" + +#. module: base +#: view:ir.actions.report.xml:0 +msgid "XML Report" +msgstr "" + +#. module: base +#: model:res.country,name:base.es +msgid "Spain" +msgstr "Испания" + +#. module: base +#: model:ir.ui.menu,name:base.menu_translation_export +msgid "Import / Export" +msgstr "" + +#. module: base +#: help:ir.actions.act_window,domain:0 +msgid "" +"Optional domain filtering of the destination data, as a Python expression" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_view_base_module_upgrade +#: model:ir.model,name:base.model_base_module_upgrade +msgid "Module Upgrade" +msgstr "" + +#. module: base +#: view:res.config.users:0 +msgid "" +"Groups are used to define access rights on objects and the visibility of " +"screens and menus" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Spanish (UY) / Español (UY)" +msgstr "" + +#. module: base +#: field:res.partner,mobile:0 +#: field:res.partner.address,mobile:0 +msgid "Mobile" +msgstr "Қалтафон" + +#. module: base +#: model:res.country,name:base.om +msgid "Oman" +msgstr "Оман" + +#. module: base +#: model:ir.actions.act_window,name:base.action_payterm_form +#: model:ir.model,name:base.model_res_payterm +msgid "Payment term" +msgstr "" + +#. module: base +#: model:res.country,name:base.nu +msgid "Niue" +msgstr "Ниуэ" + +#. module: base +#: selection:ir.cron,interval_type:0 +msgid "Work Days" +msgstr "" + +#. module: base +#: selection:ir.module.module,license:0 +msgid "Other OSI Approved Licence" +msgstr "" + +#. module: base +#: help:res.config.users,context_lang:0 +#: help:res.users,context_lang:0 +msgid "" +"Sets the language for the user's user interface, when UI translations are " +"available" +msgstr "" + +#. module: base +#: code:addons/orm.py:1043 +#, python-format +msgid "The unlink method is not implemented on this object !" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.act_menu_create +#: view:wizard.ir.model.menu.create:0 +msgid "Create Menu" +msgstr "" + +#. module: base +#: model:res.country,name:base.in +msgid "India" +msgstr "Үндістан" + +#. module: base +#: model:ir.actions.act_window,name:base.res_request_link-act +#: model:ir.ui.menu,name:base.menu_res_request_link_act +msgid "Request Reference Types" +msgstr "" + +#. module: base +#: view:ir.values:0 +msgid "client_action_multi, client_action_relate" +msgstr "" + +#. module: base +#: model:res.country,name:base.ad +msgid "Andorra, Principality of" +msgstr "" + +#. module: base +#: field:ir.module.category,child_ids:0 +#: field:res.partner.category,child_ids:0 +msgid "Child Categories" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_config_parameter +msgid "ir.config_parameter" +msgstr "" + +#. module: base +#: selection:base.language.export,format:0 +msgid "TGZ Archive" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "%B - Full month name." +msgstr "" + +#. module: base +#: view:ir.attachment:0 +#: field:ir.attachment,type:0 +#: field:ir.model,state:0 +#: field:ir.model.fields,state:0 +#: field:ir.property,type:0 +#: field:ir.server.object.lines,type:0 +#: field:ir.translation,type:0 +#: view:ir.ui.view:0 +#: view:ir.values:0 +#: field:ir.values,key:0 +#: view:res.partner:0 +#: view:res.partner.address:0 +msgid "Type" +msgstr "Түрі" + +#. module: base +#: code:addons/orm.py:210 +#, python-format +msgid "" +"Language with code \"%s\" is not defined in your system !\n" +"Define it through the Administration menu." +msgstr "" + +#. module: base +#: model:res.country,name:base.gu +msgid "Guam (USA)" +msgstr "Гуам (АҚШ)" + +#. module: base +#: model:ir.ui.menu,name:base.menu_hr_project +msgid "Human Resources Dashboard" +msgstr "" + +#. module: base +#: code:addons/base/res/res_user.py:507 +#, python-format +msgid "Setting empty passwords is not allowed for security reasons!" +msgstr "" + +#. module: base +#: selection:ir.actions.server,state:0 +#: selection:workflow.activity,kind:0 +msgid "Dummy" +msgstr "Жай" + +#. module: base +#: constraint:ir.ui.view:0 +msgid "Invalid XML for View Architecture!" +msgstr "" + +#. module: base +#: model:res.country,name:base.ky +msgid "Cayman Islands" +msgstr "Кайман ар-ы" + +#. module: base +#: model:res.country,name:base.kr +msgid "South Korea" +msgstr "Корей Республикасы" + +#. module: base +#: model:ir.actions.act_window,name:base.action_workflow_transition_form +#: model:ir.ui.menu,name:base.menu_workflow_transition +#: view:workflow.activity:0 +msgid "Transitions" +msgstr "" + +#. module: base +#: code:addons/orm.py:4020 +#, python-format +msgid "Record #%d of %s not found, cannot copy!" +msgstr "" + +#. module: base +#: field:ir.module.module,contributors:0 +msgid "Contributors" +msgstr "" + +#. module: base +#: selection:ir.property,type:0 +msgid "Char" +msgstr "Симв." + +#. module: base +#: model:ir.actions.act_window,name:base.action_publisher_warranty_contract_form +#: model:ir.ui.menu,name:base.menu_publisher_warranty_contract +msgid "Contracts" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Spanish (AR) / Español (AR)" +msgstr "" + +#. module: base +#: model:res.country,name:base.ug +msgid "Uganda" +msgstr "Уганда" + +#. module: base +#: field:ir.model.access,perm_unlink:0 +msgid "Delete Access" +msgstr "" + +#. module: base +#: model:res.country,name:base.ne +msgid "Niger" +msgstr "Нигер" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Chinese (HK)" +msgstr "" + +#. module: base +#: model:res.country,name:base.ba +msgid "Bosnia-Herzegovina" +msgstr "Босния және Герцоговина" + +#. module: base +#: view:base.language.export:0 +msgid "" +"To improve or expand the official translations, you should use directly " +"Lauchpad's web interface (Rosetta). If you need to perform mass translation, " +"Launchpad also allows uploading full .po files at once" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Spanish (GT) / Español (GT)" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "" +"%W - Week number of the year (Monday as the first day of the week) as a " +"decimal number [00,53]. All days in a new year preceding the first Monday " +"are considered to be in week 0." +msgstr "" + +#. module: base +#: field:ir.module.module,website:0 +#: field:res.partner,website:0 +msgid "Website" +msgstr "Веб сайт" + +#. module: base +#: model:res.country,name:base.gs +msgid "S. Georgia & S. Sandwich Isls." +msgstr "" + +#. module: base +#: field:ir.actions.url,url:0 +msgid "Action URL" +msgstr "" + +#. module: base +#: field:base.module.import,module_name:0 +msgid "Module Name" +msgstr "" + +#. module: base +#: model:res.country,name:base.mh +msgid "Marshall Islands" +msgstr "Маршалл аралдары" + +#. module: base +#: code:addons/base/ir/ir_model.py:328 +#, python-format +msgid "Changing the model of a field is forbidden!" +msgstr "" + +#. module: base +#: model:res.country,name:base.ht +msgid "Haiti" +msgstr "Гаити" + +#. module: base +#: view:ir.ui.view:0 +#: selection:ir.ui.view,type:0 +msgid "Search" +msgstr "Іздеу" + +#. module: base +#: code:addons/osv.py:136 +#, python-format +msgid "" +"The operation cannot be completed, probably due to the following:\n" +"- deletion: you may be trying to delete a record while other records still " +"reference it\n" +"- creation/update: a mandatory field is not correctly set" +msgstr "" + +#. module: base +#: view:ir.rule:0 +msgid "" +"2. Group-specific rules are combined together with a logical AND operator" +msgstr "" + +#. module: base +#: code:addons/base/res/res_user.py:206 +#, python-format +msgid "Operation Canceled" +msgstr "" + +#. module: base +#: help:base.language.export,lang:0 +msgid "To export a new language, do not select a language." +msgstr "" + +#. module: base +#: view:res.request:0 +msgid "Request Date" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_hr_dasboard +msgid "Dashboard" +msgstr "Аспаптар панелі" + +#. module: base +#: model:ir.ui.menu,name:base.menu_purchase_root +msgid "Purchases" +msgstr "" + +#. module: base +#: model:res.country,name:base.md +msgid "Moldavia" +msgstr "" + +#. module: base +#: view:ir.module.module:0 +msgid "Features" +msgstr "Мүмкіндіктер" + +#. module: base +#: view:ir.module.module:0 +#: report:ir.module.reference.graph:0 +msgid "Version" +msgstr "Нұсқа" + +#. module: base +#: view:ir.model.access:0 +#: field:ir.model.access,perm_read:0 +#: view:ir.rule:0 +msgid "Read Access" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_exports +msgid "ir.exports" +msgstr "" + +#. module: base +#: code:addons/base/module/wizard/base_update_translations.py:38 +#, python-format +msgid "No language with code \"%s\" exists" +msgstr "" + +#. module: base +#: code:addons/base/publisher_warranty/publisher_warranty.py:163 +#, python-format +msgid "Error during communication with the publisher warranty server." +msgstr "" + +#. module: base +#: help:ir.actions.server,email:0 +msgid "" +"Provides the fields that will be used to fetch the email address, e.g. when " +"you select the invoice, then `object.invoice_address_id.email` is the field " +"which gives the correct address" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "%Y - Year with century." +msgstr "" + +#. module: base +#: report:ir.module.reference.graph:0 +msgid "-" +msgstr "" + +#. module: base +#: view:publisher_warranty.contract.wizard:0 +msgid "" +"This wizard helps you register a publisher warranty contract in your OpenERP " +"system. After the contract has been registered, you will be able to send " +"issues directly to OpenERP." +msgstr "" + +#. module: base +#: code:addons/orm.py:1744 +#, python-format +msgid "The search method is not implemented on this object !" +msgstr "" + +#. module: base +#: view:wizard.ir.model.menu.create:0 +msgid "Create _Menu" +msgstr "" + +#. module: base +#: field:res.payterm,name:0 +msgid "Payment Term (short name)" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_bank +#: view:res.bank:0 +#: field:res.partner.bank,bank:0 +msgid "Bank" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_exports_line +msgid "ir.exports.line" +msgstr "" + +#. module: base +#: help:base.language.install,overwrite:0 +msgid "" +"If you check this box, your customized translations will be overwritten and " +"replaced by the official ones." +msgstr "" + +#. module: base +#: field:ir.actions.report.xml,report_rml:0 +msgid "Main report file path" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.ir_action_report_xml +#: field:ir.module.module,reports_by_module:0 +#: model:ir.ui.menu,name:base.menu_ir_action_report_xml +msgid "Reports" +msgstr "" + +#. module: base +#: help:ir.actions.act_window.view,multi:0 +#: help:ir.actions.report.xml,multi:0 +msgid "" +"If set to true, the action will not be displayed on the right toolbar of a " +"form view." +msgstr "" + +#. module: base +#: field:workflow,on_create:0 +msgid "On Create" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_model.py:607 +#, python-format +msgid "" +"'%s' contains too many dots. XML ids should not contain dots ! These are " +"used to refer to other modules data, as in module.reference_id" +msgstr "" + +#. module: base +#: field:partner.sms.send,user:0 +#: field:res.config.users,login:0 +#: field:res.users,login:0 +msgid "Login" +msgstr "Кіру" + +#. module: base +#: view:ir.actions.server:0 +msgid "" +"Access all the fields related to the current object using expressions, i.e. " +"object.partner_id.name " +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_country_state +msgid "Country state" +msgstr "" + +#. module: base +#: selection:ir.property,type:0 +msgid "Float" +msgstr "Қалқымалы" + +#. module: base +#: model:ir.model,name:base.model_res_request_link +msgid "res.request.link" +msgstr "" + +#. module: base +#: field:ir.actions.wizard,name:0 +msgid "Wizard Info" +msgstr "" + +#. module: base +#: view:base.language.export:0 +#: model:ir.actions.act_window,name:base.action_wizard_lang_export +#: model:ir.ui.menu,name:base.menu_wizard_lang_export +msgid "Export Translation" +msgstr "" + +#. module: base +#: help:res.log,secondary:0 +msgid "" +"Do not display this log if it belongs to the same object the user is working " +"on" +msgstr "" + +#. module: base +#: model:res.country,name:base.tp +msgid "East Timor" +msgstr "Шығыс Тимор" + +#. module: base +#: model:res.company,follow_up_msg:base.main_company +msgid "" +"Date : %(date)s\n" +"\n" +"Dear %(partner_name)s,\n" +"\n" +"Please find in attachment a reminder of all your unpaid invoices, for a " +"total amount due of:\n" +"\n" +"%(followup_amount).2f %(company_currency)s\n" +"\n" +"Thanks,\n" +"--\n" +"%(user_signature)s\n" +"%(company_name)s" +msgstr "" + +#. module: base +#: field:res.currency,accuracy:0 +msgid "Computational Accuracy" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Sinhalese / සිංහල" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_wizard_ir_model_menu_create_line +msgid "wizard.ir.model.menu.create.line" +msgstr "" + +#. module: base +#: field:ir.attachment,res_id:0 +msgid "Attached ID" +msgstr "" + +#. module: base +#: view:ir.sequence:0 +msgid "Day: %(day)s" +msgstr "" + +#. module: base +#: model:res.country,name:base.mv +msgid "Maldives" +msgstr "Мальдив ар-ы" + +#. module: base +#: help:ir.values,res_id:0 +msgid "Keep 0 if the action must appear on all resources." +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_rule +msgid "ir.rule" +msgstr "" + +#. module: base +#: selection:ir.cron,interval_type:0 +msgid "Days" +msgstr "күн" + +#. module: base +#: help:ir.actions.server,condition:0 +msgid "" +"Condition that is to be tested before action is executed, e.g. " +"object.list_price > object.cost_price" +msgstr "" + +#. module: base +#: code:addons/base/res/partner/partner.py:155 +#: code:addons/base/res/res_company.py:66 +#, python-format +msgid " (copy)" +msgstr " (көшірме)" + +#. module: base +#: view:res.lang:0 +msgid "7. %H:%M:%S ==> 18:25:20" +msgstr "" + +#. module: base +#: view:res.partner:0 +#: view:res.partner.category:0 +#: field:res.partner.category,partner_ids:0 +msgid "Partners" +msgstr "" + +#. module: base +#: field:res.partner.category,parent_left:0 +msgid "Left parent" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.res_widget_act_window +#: model:ir.ui.menu,name:base.menu_res_widget_act_window +msgid "Homepage Widgets" +msgstr "" + +#. module: base +#: help:ir.actions.server,message:0 +msgid "" +"Specify the message. You can use the fields from the object. e.g. `Dear [[ " +"object.partner_id.name ]]`" +msgstr "" + +#. module: base +#: field:ir.attachment,res_model:0 +msgid "Attached Model" +msgstr "" + +#. module: base +#: view:ir.rule:0 +msgid "Domain Setup" +msgstr "" + +#. module: base +#: field:ir.actions.server,trigger_name:0 +msgid "Trigger Name" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_model_access +msgid "ir.model.access" +msgstr "" + +#. module: base +#: field:ir.cron,priority:0 +#: field:res.request,priority:0 +#: field:res.request.link,priority:0 +msgid "Priority" +msgstr "Маңыздылығы" + +#. module: base +#: field:workflow.transition,act_from:0 +msgid "Source Activity" +msgstr "" + +#. module: base +#: view:ir.sequence:0 +msgid "Legend (for prefix, suffix)" +msgstr "" + +#. module: base +#: selection:ir.server.object.lines,type:0 +msgid "Formula" +msgstr "Формула" + +#. module: base +#: code:addons/base/res/res_user.py:389 +#, python-format +msgid "Can not remove root user!" +msgstr "" + +#. module: base +#: model:res.country,name:base.mw +msgid "Malawi" +msgstr "Малави" + +#. module: base +#: code:addons/base/res/res_user.py:51 +#: code:addons/base/res/res_user.py:413 +#, python-format +msgid "%s (copy)" +msgstr "" + +#. module: base +#: field:res.partner.address,type:0 +msgid "Address Type" +msgstr "" + +#. module: base +#: view:ir.ui.menu:0 +msgid "Full Path" +msgstr "Толық жолы" + +#. module: base +#: view:res.request:0 +msgid "References" +msgstr "References" + +#. module: base +#: view:res.lang:0 +msgid "" +"%U - Week number of the year (Sunday as the first day of the week) as a " +"decimal number [00,53]. All days in a new year preceding the first Sunday " +"are considered to be in week 0." +msgstr "" + +#. module: base +#: view:ir.ui.view:0 +msgid "Advanced" +msgstr "Жетелеу" + +#. module: base +#: model:res.country,name:base.fi +msgid "Finland" +msgstr "Финляндия" + +#. module: base +#: selection:ir.actions.act_window,view_type:0 +#: selection:ir.actions.act_window.view,view_mode:0 +#: view:ir.ui.view:0 +#: selection:ir.ui.view,type:0 +#: selection:wizard.ir.model.menu.create.line,view_type:0 +msgid "Tree" +msgstr "Бұтақ" + +#. module: base +#: help:res.config.users,password:0 +msgid "" +"Keep empty if you don't want the user to be able to connect on the system." +msgstr "" + +#. module: base +#: view:ir.actions.server:0 +msgid "Create / Write / Copy" +msgstr "" + +#. module: base +#: view:base.language.export:0 +msgid "https://help.launchpad.net/Translations" +msgstr "" + +#. module: base +#: field:ir.actions.act_window,view_mode:0 +msgid "View Mode" +msgstr "" + +#. module: base +#: view:base.language.import:0 +msgid "" +"When using CSV format, please also check that the first line of your file is " +"one of the following:" +msgstr "" + +#. module: base +#: code:addons/fields.py:114 +#, python-format +msgid "Not implemented search_memory method !" +msgstr "" + +#. module: base +#: view:res.log:0 +msgid "Logs" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Spanish / Español" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Korean (KP) / 한국어 (KP)" +msgstr "" + +#. module: base +#: view:base.module.update:0 +msgid "" +"This wizard will scan all module repositories on the server side to detect " +"newly added modules as well as any change to existing modules." +msgstr "" + +#. module: base +#: field:res.company,logo:0 +msgid "Logo" +msgstr "" + +#. module: base +#: view:res.partner.address:0 +msgid "Search Contact" +msgstr "" + +#. module: base +#: view:ir.module.module:0 +msgid "Uninstall (beta)" +msgstr "" + +#. module: base +#: selection:ir.actions.act_window,target:0 +#: selection:ir.actions.url,target:0 +msgid "New Window" +msgstr "" + +#. module: base +#: model:res.country,name:base.bs +msgid "Bahamas" +msgstr "" + +#. module: base +#: code:addons/base/res/partner/partner.py:250 +#, python-format +msgid "" +"Couldn't generate the next id because some partners have an alphabetic id !" +msgstr "" + +#. module: base +#: view:ir.attachment:0 +msgid "Attachment" +msgstr "" + +#. module: base +#: model:res.country,name:base.ie +msgid "Ireland" +msgstr "" + +#. module: base +#: field:base.module.update,update:0 +msgid "Number of modules updated" +msgstr "" + +#. module: base +#: code:addons/fields.py:100 +#, python-format +msgid "Not implemented set_memory method !" +msgstr "" + +#. module: base +#: view:workflow.activity:0 +msgid "Workflow Activity" +msgstr "" + +#. module: base +#: view:ir.rule:0 +msgid "" +"Example: GLOBAL_RULE_1 AND GLOBAL_RULE_2 AND ( (GROUP_A_RULE_1 AND " +"GROUP_A_RULE_2) OR (GROUP_B_RULE_1 AND GROUP_B_RULE_2) )" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,help:base.action_ui_view +msgid "" +"Views allows you to personalize each view of OpenERP. You can add new " +"fields, move fields, rename them or delete the ones that you do not need." +msgstr "" + +#. module: base +#: field:ir.actions.act_window,groups_id:0 +#: model:ir.actions.act_window,name:base.action_res_groups +#: view:ir.actions.report.xml:0 +#: field:ir.actions.report.xml,groups_id:0 +#: view:ir.actions.todo:0 +#: field:ir.actions.todo,groups_id:0 +#: field:ir.actions.wizard,groups_id:0 +#: view:ir.model:0 +#: field:ir.model.fields,groups:0 +#: field:ir.rule,groups:0 +#: view:ir.ui.menu:0 +#: field:ir.ui.menu,groups_id:0 +#: model:ir.ui.menu,name:base.menu_action_res_groups +#: field:res.config.users,groups_id:0 +#: view:res.groups:0 +#: view:res.users:0 +#: field:res.users,groups_id:0 +msgid "Groups" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Spanish (CL) / Español (CL)" +msgstr "" + +#. module: base +#: view:res.config.users:0 +msgid "" +"Create additional users and assign them groups that will allow them to have " +"access to selected functionalities within the system. Click on 'Done' if you " +"do not wish to add more users at this stage, you can always do this later." +msgstr "" + +#. module: base +#: model:res.country,name:base.bz +msgid "Belize" +msgstr "" + +#. module: base +#: model:res.country,name:base.ge +msgid "Georgia" +msgstr "" + +#. module: base +#: model:res.country,name:base.pl +msgid "Poland" +msgstr "" + +#. module: base +#: help:ir.actions.act_window,view_mode:0 +msgid "" +"Comma-separated list of allowed view modes, such as 'form', 'tree', " +"'calendar', etc. (Default: tree,form)" +msgstr "" + +#. module: base +#: code:addons/orm.py:3147 +#, python-format +msgid "A document was modified since you last viewed it (%s:%d)" +msgstr "" + +#. module: base +#: view:workflow:0 +msgid "Workflow Editor" +msgstr "" + +#. module: base +#: selection:ir.module.module,state:0 +#: selection:ir.module.module.dependency,state:0 +msgid "To be removed" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_sequence +msgid "ir.sequence" +msgstr "" + +#. module: base +#: help:ir.actions.server,expression:0 +msgid "" +"Enter the field/expression that will return the list. E.g. select the sale " +"order in Object, and you can have loop on the sales order line. Expression = " +"`object.order_line`." +msgstr "" + +#. module: base +#: field:ir.property,fields_id:0 +#: selection:ir.translation,type:0 +#: field:multi_company.default,field_id:0 +msgid "Field" +msgstr "" + +#. module: base +#: view:ir.rule:0 +msgid "Groups (no group = global)" +msgstr "" + +#. module: base +#: model:res.country,name:base.fo +msgid "Faroe Islands" +msgstr "" + +#. module: base +#: selection:res.config.users,view:0 +#: selection:res.config.view,view:0 +#: selection:res.users,view:0 +msgid "Simplified" +msgstr "" + +#. module: base +#: model:res.country,name:base.st +msgid "Saint Tome (Sao Tome) and Principe" +msgstr "" + +#. module: base +#: selection:res.partner.address,type:0 +msgid "Invoice" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Portugese (BR) / Português (BR)" +msgstr "" + +#. module: base +#: model:res.country,name:base.bb +msgid "Barbados" +msgstr "" + +#. module: base +#: model:res.country,name:base.mg +msgid "Madagascar" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_model.py:96 +#, python-format +msgid "" +"The Object name must start with x_ and not contain any special character !" +msgstr "" + +#. module: base +#: field:ir.actions.configuration.wizard,note:0 +msgid "Next Wizard" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_menu_admin +#: view:ir.ui.menu:0 +#: field:ir.ui.menu,name:0 +msgid "Menu" +msgstr "" + +#. module: base +#: field:res.currency,rate:0 +msgid "Current Rate" +msgstr "" + +#. module: base +#: field:ir.ui.view.custom,ref_id:0 +msgid "Original View" +msgstr "" + +#. module: base +#: view:ir.values:0 +msgid "Action To Launch" +msgstr "" + +#. module: base +#: field:ir.actions.url,target:0 +msgid "Action Target" +msgstr "" + +#. module: base +#: model:res.country,name:base.ai +msgid "Anguilla" +msgstr "" + +#. module: base +#: field:ir.ui.view_sc,name:0 +msgid "Shortcut Name" +msgstr "" + +#. module: base +#: help:ir.actions.act_window,limit:0 +msgid "Default limit for the list view" +msgstr "" + +#. module: base +#: help:ir.actions.server,write_id:0 +msgid "" +"Provide the field name that the record id refers to for the write operation. " +"If it is empty it will refer to the active id of the object." +msgstr "" + +#. module: base +#: model:res.country,name:base.zw +msgid "Zimbabwe" +msgstr "" + +#. module: base +#: view:base.module.update:0 +msgid "Please be patient, as this operation may take a few seconds..." +msgstr "" + +#. module: base +#: help:ir.values,action_id:0 +msgid "This field is not used, it only helps you to select the right action." +msgstr "" + +#. module: base +#: field:ir.actions.server,email:0 +msgid "Email Address" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "French (BE) / Français (BE)" +msgstr "" + +#. module: base +#: view:ir.actions.server:0 +#: field:workflow.activity,action_id:0 +msgid "Server Action" +msgstr "" + +#. module: base +#: model:res.country,name:base.tt +msgid "Trinidad and Tobago" +msgstr "" + +#. module: base +#: model:res.country,name:base.lv +msgid "Latvia" +msgstr "" + +#. module: base +#: view:ir.values:0 +msgid "Values" +msgstr "" + +#. module: base +#: view:ir.actions.server:0 +msgid "Field Mappings" +msgstr "" + +#. module: base +#: view:base.language.export:0 +msgid "Export Translations" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_custom +msgid "Customization" +msgstr "" + +#. module: base +#: model:res.country,name:base.py +msgid "Paraguay" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_actions_act_window_close +msgid "ir.actions.act_window_close" +msgstr "" + +#. module: base +#: field:ir.server.object.lines,col1:0 +msgid "Destination" +msgstr "" + +#. module: base +#: model:res.country,name:base.lt +msgid "Lithuania" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_view_partner_clear_ids +#: model:ir.model,name:base.model_partner_clear_ids +#: view:partner.clear.ids:0 +msgid "Clear IDs" +msgstr "" + +#. module: base +#: help:ir.cron,model:0 +msgid "" +"Name of object whose function will be called when this scheduler will run. " +"e.g. 'res.partener'" +msgstr "" + +#. module: base +#: code:addons/orm.py:1040 +#, python-format +msgid "The perm_read method is not implemented on this object !" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "%y - Year without century [00,99]." +msgstr "" + +#. module: base +#: model:res.country,name:base.si +msgid "Slovenia" +msgstr "" + +#. module: base +#: model:res.country,name:base.pk +msgid "Pakistan" +msgstr "" + +#. module: base +#: code:addons/orm.py:1350 +#, python-format +msgid "Invalid Object Architecture!" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_email_gateway_form +msgid "Messages" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_model.py:303 +#: code:addons/base/ir/ir_model.py:317 +#: code:addons/base/ir/ir_model.py:319 +#: code:addons/base/ir/ir_model.py:321 +#: code:addons/base/ir/ir_model.py:328 +#: code:addons/base/ir/ir_model.py:331 +#: code:addons/base/module/wizard/base_update_translations.py:38 +#, python-format +msgid "Error!" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "%p - Equivalent of either AM or PM." +msgstr "" + +#. module: base +#: view:ir.actions.server:0 +msgid "Iteration Actions" +msgstr "" + +#. module: base +#: help:multi_company.default,company_id:0 +msgid "Company where the user is connected" +msgstr "" + +#. module: base +#: field:publisher_warranty.contract,date_stop:0 +msgid "Ending Date" +msgstr "" + +#. module: base +#: model:res.country,name:base.nz +msgid "New Zealand" +msgstr "" + +#. module: base +#: code:addons/orm.py:3366 +#, python-format +msgid "" +"One of the records you are trying to modify has already been deleted " +"(Document type: %s)." +msgstr "" + +#. module: base +#: model:ir.actions.act_window,help:base.action_country +msgid "" +"Display and manage the list of all countries that can be assigned to your " +"partner records. You can create or delete countries to make sure the ones " +"you are working on will be maintained." +msgstr "" + +#. module: base +#: model:res.partner.category,name:base.res_partner_category_7 +msgid "Openstuff.net" +msgstr "" + +#. module: base +#: model:res.country,name:base.nf +msgid "Norfolk Island" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Korean (KR) / 한국어 (KR)" +msgstr "" + +#. module: base +#: help:ir.model.fields,model:0 +msgid "The technical name of the model this field belongs to" +msgstr "" + +#. module: base +#: field:ir.actions.server,action_id:0 +#: selection:ir.actions.server,state:0 +msgid "Client Action" +msgstr "" + +#. module: base +#: model:res.country,name:base.bd +msgid "Bangladesh" +msgstr "" + +#. module: base +#: constraint:res.company:0 +msgid "Error! You can not create recursive companies." +msgstr "" + +#. module: base +#: selection:publisher_warranty.contract,state:0 +msgid "Valid" +msgstr "" + +#. module: base +#: selection:ir.translation,type:0 +msgid "XSL" +msgstr "" + +#. module: base +#: code:addons/base/module/module.py:322 +#, python-format +msgid "Can not upgrade module '%s'. It is not installed." +msgstr "" + +#. module: base +#: model:res.country,name:base.cu +msgid "Cuba" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_partner_event +msgid "res.partner.event" +msgstr "" + +#. module: base +#: model:res.widget,title:base.facebook_widget +msgid "Facebook" +msgstr "" + +#. module: base +#: model:res.country,name:base.am +msgid "Armenia" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.ir_property_form +#: model:ir.ui.menu,name:base.menu_ir_property_form_all +msgid "Configuration Parameters" +msgstr "" + +#. module: base +#: constraint:ir.cron:0 +msgid "Invalid arguments" +msgstr "" + +#. module: base +#: model:res.country,name:base.se +msgid "Sweden" +msgstr "" + +#. module: base +#: selection:ir.actions.act_window.view,view_mode:0 +#: selection:ir.ui.view,type:0 +#: selection:wizard.ir.model.menu.create.line,view_type:0 +msgid "Gantt" +msgstr "" + +#. module: base +#: view:ir.property:0 +msgid "Property" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_partner_bank_type +#: view:res.partner.bank.type:0 +msgid "Bank Account Type" +msgstr "" + +#. module: base +#: field:base.language.export,config_logo:0 +#: field:base.language.import,config_logo:0 +#: field:base.language.install,config_logo:0 +#: field:base.module.import,config_logo:0 +#: field:base.module.update,config_logo:0 +#: field:base.update.translations,config_logo:0 +#: field:ir.actions.configuration.wizard,config_logo:0 +#: field:ir.wizard.screen,config_logo:0 +#: field:publisher_warranty.contract.wizard,config_logo:0 +#: field:res.config,config_logo:0 +#: field:res.config.installer,config_logo:0 +#: field:res.config.users,config_logo:0 +#: field:res.config.view,config_logo:0 +msgid "Image" +msgstr "" + +#. module: base +#: view:ir.actions.server:0 +msgid "Iteration Action Configuration" +msgstr "" + +#. module: base +#: selection:publisher_warranty.contract,state:0 +msgid "Canceled" +msgstr "" + +#. module: base +#: model:res.country,name:base.at +msgid "Austria" +msgstr "" + +#. module: base +#: selection:base.language.install,state:0 +#: selection:base.module.import,state:0 +#: selection:base.module.update,state:0 +msgid "done" +msgstr "" + +#. module: base +#: selection:ir.actions.act_window.view,view_mode:0 +#: model:ir.ui.menu,name:base.menu_calendar_configuration +#: selection:ir.ui.view,type:0 +#: selection:wizard.ir.model.menu.create.line,view_type:0 +msgid "Calendar" +msgstr "" + +#. module: base +#: field:res.partner.address,partner_id:0 +msgid "Partner Name" +msgstr "" + +#. module: base +#: field:workflow.activity,signal_send:0 +msgid "Signal (subflow.*)" +msgstr "" + +#. module: base +#: model:res.partner.category,name:base.res_partner_category_17 +msgid "HR sector" +msgstr "" + +#. module: base +#: code:addons/orm.py:3817 +#, python-format +msgid "" +"Invalid \"order\" specified. A valid \"order\" specification is a comma-" +"separated list of valid field names (optionally followed by asc/desc for the " +"direction)" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_module_module_dependency +msgid "Module dependency" +msgstr "" + +#. module: base +#: selection:publisher_warranty.contract.wizard,state:0 +msgid "Draft" +msgstr "" + +#. module: base +#: selection:res.config.users,view:0 +#: selection:res.config.view,view:0 +#: selection:res.users,view:0 +msgid "Extended" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,help:base.action_partner_title_contact +msgid "" +"Manage the contact titles you want to have available in your system and the " +"way you want to print them in letters and other documents. Some example: " +"Mr., Mrs. " +msgstr "" + +#. module: base +#: field:res.company,rml_footer1:0 +msgid "Report Footer 1" +msgstr "" + +#. module: base +#: field:res.company,rml_footer2:0 +msgid "Report Footer 2" +msgstr "" + +#. module: base +#: view:ir.model.access:0 +#: view:res.groups:0 +#: field:res.groups,model_access:0 +msgid "Access Controls" +msgstr "" + +#. module: base +#: view:ir.module.module:0 +#: field:ir.module.module,dependencies_id:0 +msgid "Dependencies" +msgstr "" + +#. module: base +#: field:multi_company.default,company_id:0 +msgid "Main Company" +msgstr "" + +#. module: base +#: field:ir.ui.menu,web_icon_hover:0 +msgid "Web Icon File (hover)" +msgstr "" + +#. module: base +#: view:ir.actions.server:0 +msgid "" +"If you use a formula type, use a python expression using the variable " +"'object'." +msgstr "" + +#. module: base +#: field:res.partner.address,birthdate:0 +msgid "Birthdate" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_partner_title_contact +#: model:ir.ui.menu,name:base.menu_partner_title_contact +msgid "Contact Titles" +msgstr "" + +#. module: base +#: view:base.language.import:0 +msgid "" +"Please double-check that the file encoding is set to UTF-8 (sometimes called " +"Unicode) when the translator exports it." +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Spanish (DO) / Español (DO)" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_workflow_activity +msgid "workflow.activity" +msgstr "" + +#. module: base +#: help:ir.ui.view_sc,res_id:0 +msgid "" +"Reference of the target resource, whose model/table depends on the 'Resource " +"Name' field." +msgstr "" + +#. module: base +#: field:ir.model.fields,select_level:0 +msgid "Searchable" +msgstr "" + +#. module: base +#: model:res.country,name:base.uy +msgid "Uruguay" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Finnish / Suomi" +msgstr "" + +#. module: base +#: field:ir.rule,perm_write:0 +msgid "Apply For Write" +msgstr "" + +#. module: base +#: field:ir.sequence,prefix:0 +msgid "Prefix" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "German / Deutsch" +msgstr "" + +#. module: base +#: help:ir.actions.server,trigger_name:0 +msgid "Select the Signal name that is to be used as the trigger." +msgstr "" + +#. module: base +#: view:ir.actions.server:0 +msgid "Fields Mapping" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Portugese / Português" +msgstr "" + +#. module: base +#: model:res.partner.title,name:base.res_partner_title_sir +msgid "Sir" +msgstr "" + +#. module: base +#: code:addons/orm.py:1622 +#, python-format +msgid "There is no view of type '%s' defined for the structure!" +msgstr "" + +#. module: base +#: field:ir.default,ref_id:0 +msgid "ID Ref." +msgstr "" + +#. module: base +#: model:ir.actions.server,name:base.action_start_configurator +#: model:ir.ui.menu,name:base.menu_view_base_module_configuration +msgid "Start Configuration" +msgstr "" + +#. module: base +#: model:res.country,name:base.mt +msgid "Malta" +msgstr "" + +#. module: base +#: field:ir.actions.server,fields_lines:0 +msgid "Field Mappings." +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_module_module +#: view:ir.model.data:0 +#: field:ir.model.data,module:0 +#: view:ir.module.module:0 +#: field:ir.module.module.dependency,module_id:0 +#: report:ir.module.reference.graph:0 +#: field:ir.translation,module:0 +msgid "Module" +msgstr "" + +#. module: base +#: field:ir.attachment,description:0 +#: view:ir.module.module:0 +#: field:ir.module.module,description:0 +#: field:res.partner.bank,name:0 +#: view:res.partner.event:0 +#: field:res.partner.event,description:0 +#: view:res.request:0 +msgid "Description" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_workflow_instance_form +#: model:ir.ui.menu,name:base.menu_workflow_instance +msgid "Instances" +msgstr "" + +#. module: base +#: model:res.country,name:base.aq +msgid "Antarctica" +msgstr "" + +#. module: base +#: field:ir.actions.report.xml,auto:0 +msgid "Custom python parser" +msgstr "" + +#. module: base +#: view:base.language.import:0 +msgid "_Import" +msgstr "" + +#. module: base +#: view:res.partner.canal:0 +msgid "Channel" +msgstr "" + +#. module: base +#: field:res.lang,grouping:0 +msgid "Separator Format" +msgstr "" + +#. module: base +#: selection:publisher_warranty.contract,state:0 +msgid "Unvalidated" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.next_id_9 +msgid "Database Structure" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_partner_mass_mail +#: model:ir.model,name:base.model_partner_wizard_spam +#: view:partner.wizard.spam:0 +msgid "Mass Mailing" +msgstr "" + +#. module: base +#: model:res.country,name:base.yt +msgid "Mayotte" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_actions.py:597 +#, python-format +msgid "Please specify an action to launch !" +msgstr "" + +#. module: base +#: view:res.payterm:0 +msgid "Payment Term" +msgstr "" + +#. module: base +#: selection:res.lang,direction:0 +msgid "Right-to-Left" +msgstr "" + +#. module: base +#: view:ir.actions.act_window:0 +#: model:ir.actions.act_window,name:base.actions_ir_filters_view +#: view:ir.filters:0 +#: model:ir.model,name:base.model_ir_filters +#: model:ir.ui.menu,name:base.menu_ir_filters +msgid "Filters" +msgstr "" + +#. module: base +#: code:addons/orm.py:758 +#, python-format +msgid "Please check that all your lines have %d columns." +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.ir_cron_act +#: view:ir.cron:0 +#: model:ir.ui.menu,name:base.menu_ir_cron_act +msgid "Scheduled Actions" +msgstr "" + +#. module: base +#: field:res.partner.address,title:0 +#: field:res.partner.title,name:0 +#: field:res.widget,title:0 +msgid "Title" +msgstr "" + +#. module: base +#: help:ir.property,res_id:0 +msgid "If not set, acts as a default value for new resources" +msgstr "" + +#. module: base +#: code:addons/orm.py:3448 +#, python-format +msgid "Recursivity Detected." +msgstr "" + +#. module: base +#: code:addons/base/module/module.py:262 +#, python-format +msgid "Recursion error in modules dependencies !" +msgstr "" + +#. module: base +#: view:base.language.install:0 +msgid "" +"This wizard helps you add a new language to your OpenERP system. After " +"loading a new language it becomes available as default interface language " +"for users and partners." +msgstr "" + +#. module: base +#: view:ir.model:0 +msgid "Create a Menu" +msgstr "" + +#. module: base +#: help:res.partner,vat:0 +msgid "" +"Value Added Tax number. Check the box if the partner is subjected to the " +"VAT. Used by the VAT legal statement." +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_maintenance_contract +msgid "maintenance.contract" +msgstr "" + +#. module: base +#: model:res.country,name:base.ru +msgid "Russian Federation" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Urdu / اردو" +msgstr "" + +#. module: base +#: field:res.company,name:0 +msgid "Company Name" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_country +#: model:ir.ui.menu,name:base.menu_country_partner +msgid "Countries" +msgstr "" + +#. module: base +#: selection:ir.translation,type:0 +msgid "RML (deprecated - use Report)" +msgstr "" + +#. module: base +#: view:ir.rule:0 +msgid "Record rules" +msgstr "" + +#. module: base +#: view:ir.property:0 +msgid "Field Information" +msgstr "" + +#. module: base +#: view:ir.actions.todo:0 +msgid "Search Actions" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_view_partner_wizard_ean_check +#: view:partner.wizard.ean.check:0 +msgid "Ean check" +msgstr "" + +#. module: base +#: field:res.partner,vat:0 +msgid "VAT" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "12. %w ==> 5 ( Friday is the 6th day)" +msgstr "" + +#. module: base +#: constraint:res.partner.category:0 +msgid "Error ! You can not create recursive categories." +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "%x - Appropriate date representation." +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "%d - Day of the month [01,31]." +msgstr "" + +#. module: base +#: model:res.country,name:base.tj +msgid "Tajikistan" +msgstr "" + +#. module: base +#: selection:ir.module.module,license:0 +msgid "GPL-2 or later version" +msgstr "" + +#. module: base +#: model:res.partner.title,shortcut:base.res_partner_title_sir +msgid "M." +msgstr "" + +#. module: base +#: code:addons/base/module/module.py:429 +#, python-format +msgid "" +"Can not create the module file:\n" +" %s" +msgstr "" + +#. module: base +#: code:addons/orm.py:2973 +#, python-format +msgid "" +"Operation prohibited by access rules, or performed on an already deleted " +"document (Operation: read, Document type: %s)." +msgstr "" + +#. module: base +#: model:res.country,name:base.nr +msgid "Nauru" +msgstr "" + +#. module: base +#: code:addons/base/module/module.py:200 +#, python-format +msgid "The certificate ID of the module must be unique !" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_property +msgid "ir.property" +msgstr "" + +#. module: base +#: selection:ir.actions.act_window,view_type:0 +#: selection:ir.actions.act_window.view,view_mode:0 +#: view:ir.ui.view:0 +#: selection:ir.ui.view,type:0 +#: selection:wizard.ir.model.menu.create.line,view_type:0 +msgid "Form" +msgstr "" + +#. module: base +#: model:res.country,name:base.me +msgid "Montenegro" +msgstr "" + +#. module: base +#: view:ir.cron:0 +msgid "Technical Data" +msgstr "" + +#. module: base +#: view:res.partner:0 +#: field:res.partner,category_id:0 +msgid "Categories" +msgstr "" + +#. module: base +#: view:base.language.import:0 +msgid "" +"If you need another language than the official ones available, you can " +"import a language pack from here. Other OpenERP languages than the official " +"ones can be found on launchpad." +msgstr "" + +#. module: base +#: view:ir.module.module:0 +#: selection:ir.module.module,state:0 +#: selection:ir.module.module.dependency,state:0 +msgid "To be upgraded" +msgstr "" + +#. module: base +#: model:res.country,name:base.ly +msgid "Libya" +msgstr "" + +#. module: base +#: model:res.country,name:base.cf +msgid "Central African Republic" +msgstr "" + +#. module: base +#: model:res.country,name:base.li +msgid "Liechtenstein" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_partner_sms_send +#: view:partner.sms.send:0 +msgid "Send SMS" +msgstr "" + +#. module: base +#: field:res.partner,ean13:0 +msgid "EAN13" +msgstr "" + +#. module: base +#: code:addons/orm.py:1622 +#, python-format +msgid "Invalid Architecture!" +msgstr "" + +#. module: base +#: model:res.country,name:base.pt +msgid "Portugal" +msgstr "" + +#. module: base +#: sql_constraint:ir.model.data:0 +msgid "" +"You cannot have multiple records with the same id for the same module !" +msgstr "" + +#. module: base +#: field:ir.module.module,certificate:0 +msgid "Quality Certificate" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "6. %d, %m ==> 05, 12" +msgstr "" + +#. module: base +#: field:res.config.users,date:0 +#: field:res.users,date:0 +msgid "Last Connection" +msgstr "" + +#. module: base +#: field:ir.actions.act_window,help:0 +msgid "Action description" +msgstr "" + +#. module: base +#: help:res.partner,customer:0 +msgid "Check this box if the partner is a customer." +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.res_lang_act_window +#: model:ir.model,name:base.model_res_lang +#: model:ir.ui.menu,name:base.menu_res_lang_act_window +#: view:res.lang:0 +msgid "Languages" +msgstr "" + +#. module: base +#: selection:workflow.activity,join_mode:0 +#: selection:workflow.activity,split_mode:0 +msgid "Xor" +msgstr "" + +#. module: base +#: model:res.country,name:base.ec +msgid "Ecuador" +msgstr "" + +#. module: base +#: code:addons/base/module/wizard/base_export_language.py:52 +#, python-format +msgid "" +"Save this document to a .CSV file and open it with your favourite " +"spreadsheet software. The file encoding is UTF-8. You have to translate the " +"latest column before reimporting it." +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_partner_customer_form +#: model:ir.actions.act_window,name:base.action_partner_form +#: model:ir.ui.menu,name:base.menu_partner_form +#: view:res.partner:0 +msgid "Customers" +msgstr "" + +#. module: base +#: model:res.country,name:base.au +msgid "Australia" +msgstr "" + +#. module: base +#: help:res.partner,lang:0 +msgid "" +"If the selected language is loaded in the system, all documents related to " +"this partner will be printed in this language. If not, it will be english." +msgstr "" + +#. module: base +#: report:ir.module.reference.graph:0 +msgid "Menu :" +msgstr "" + +#. module: base +#: selection:ir.model.fields,state:0 +msgid "Base Field" +msgstr "" + +#. module: base +#: view:publisher_warranty.contract:0 +msgid "Validate" +msgstr "" + +#. module: base +#: field:ir.actions.todo,restart:0 +msgid "Restart" +msgstr "" + +#. module: base +#: field:ir.actions.report.xml,report_sxw_content:0 +#: field:ir.actions.report.xml,report_sxw_content_data:0 +msgid "SXW content" +msgstr "" + +#. module: base +#: view:ir.actions.wizard:0 +#: field:wizard.ir.model.menu.create.line,wizard_id:0 +msgid "Wizard" +msgstr "" + +#. module: base +#: view:ir.cron:0 +msgid "Action to Trigger" +msgstr "" + +#. module: base +#: code:addons/base/res/res_user.py:136 +#, python-format +msgid "\"email_from\" needs to be set to send welcome mails to users" +msgstr "" + +#. module: base +#: selection:ir.translation,type:0 +msgid "Constraint" +msgstr "" + +#. module: base +#: selection:ir.values,key:0 +#: selection:res.partner.address,type:0 +msgid "Default" +msgstr "" + +#. module: base +#: view:ir.model.fields:0 +#: field:ir.model.fields,required:0 +#: field:res.partner.bank.type.field,required:0 +msgid "Required" +msgstr "" + +#. module: base +#: view:res.users:0 +msgid "Default Filters" +msgstr "" + +#. module: base +#: field:res.request.history,name:0 +msgid "Summary" +msgstr "" + +#. module: base +#: field:multi_company.default,expression:0 +msgid "Expression" +msgstr "" + +#. module: base +#: help:ir.actions.server,subject:0 +msgid "" +"Specify the subject. You can use fields from the object, e.g. `Hello [[ " +"object.partner_id.name ]]`" +msgstr "" + +#. module: base +#: view:res.company:0 +msgid "Header/Footer" +msgstr "" + +#. module: base +#: help:ir.actions.act_window,help:0 +msgid "" +"Optional help text for the users with a description of the target view, such " +"as its usage and purpose." +msgstr "" + +#. module: base +#: model:res.country,name:base.va +msgid "Holy See (Vatican City State)" +msgstr "" + +#. module: base +#: field:base.module.import,module_file:0 +msgid "Module .ZIP file" +msgstr "" + +#. module: base +#: field:ir.ui.view,xml_id:0 +msgid "XML ID" +msgstr "" + +#. module: base +#: model:res.partner.category,name:base.res_partner_category_16 +msgid "Telecom sector" +msgstr "" + +#. module: base +#: field:workflow.transition,trigger_model:0 +msgid "Trigger Object" +msgstr "" + +#. module: base +#: view:res.users:0 +msgid "Current Activity" +msgstr "" + +#. module: base +#: view:workflow.activity:0 +#: field:workflow.activity,in_transitions:0 +msgid "Incoming Transitions" +msgstr "" + +#. module: base +#: model:res.country,name:base.sr +msgid "Suriname" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.marketing_menu +msgid "Marketing" +msgstr "" + +#. module: base +#: view:res.partner.bank:0 +#: model:res.partner.bank.type,name:base.bank_normal +msgid "Bank account" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Spanish (HN) / Español (HN)" +msgstr "" + +#. module: base +#: view:ir.sequence.type:0 +msgid "Sequence Type" +msgstr "" + +#. module: base +#: view:ir.ui.view.custom:0 +msgid "Customized Architecture" +msgstr "" + +#. module: base +#: field:ir.module.module,license:0 +msgid "License" +msgstr "" + +#. module: base +#: field:ir.attachment,url:0 +msgid "Url" +msgstr "" + +#. module: base +#: selection:ir.actions.todo,restart:0 +msgid "Always" +msgstr "" + +#. module: base +#: selection:ir.translation,type:0 +msgid "SQL Constraint" +msgstr "" + +#. module: base +#: field:ir.actions.server,srcmodel_id:0 +#: field:ir.model.fields,model_id:0 +msgid "Model" +msgstr "" + +#. module: base +#: view:base.language.install:0 +msgid "" +"The selected language has been successfully installed. You must change the " +"preferences of the user and open a new menu to view the changes." +msgstr "" + +#. module: base +#: sql_constraint:ir.config_parameter:0 +msgid "Key must be unique." +msgstr "" + +#. module: base +#: view:ir.actions.act_window:0 +msgid "Open a Window" +msgstr "" + +#. module: base +#: model:res.country,name:base.gq +msgid "Equatorial Guinea" +msgstr "" + +#. module: base +#: view:base.module.import:0 +#: model:ir.actions.act_window,name:base.action_view_base_module_import +msgid "Module Import" +msgstr "" + +#. module: base +#: field:res.bank,zip:0 +#: field:res.partner.address,zip:0 +#: field:res.partner.bank,zip:0 +msgid "Zip" +msgstr "" + +#. module: base +#: view:ir.module.module:0 +#: field:ir.module.module,author:0 +msgid "Author" +msgstr "" + +#. module: base +#: model:res.country,name:base.mk +msgid "FYROM" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "%c - Appropriate date and time representation." +msgstr "" + +#. module: base +#: code:addons/base/res/res_config.py:422 +#, python-format +msgid "" +"Your database is now fully configured.\n" +"\n" +"Click 'Continue' and enjoy your OpenERP experience..." +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Hebrew / עִבְרִי" +msgstr "" + +#. module: base +#: model:res.country,name:base.bo +msgid "Bolivia" +msgstr "" + +#. module: base +#: model:res.country,name:base.gh +msgid "Ghana" +msgstr "" + +#. module: base +#: field:res.lang,direction:0 +msgid "Direction" +msgstr "" + +#. module: base +#: view:ir.actions.act_window:0 +#: model:ir.actions.act_window,name:base.action_ui_view +#: field:ir.actions.act_window,view_ids:0 +#: field:ir.actions.act_window,views:0 +#: field:ir.module.module,views_by_module:0 +#: model:ir.ui.menu,name:base.menu_action_ui_view +#: view:ir.ui.view:0 +msgid "Views" +msgstr "" + +#. module: base +#: view:res.groups:0 +#: field:res.groups,rule_groups:0 +msgid "Rules" +msgstr "" + +#. module: base +#: code:addons/base/module/module.py:216 +#, python-format +msgid "You try to remove a module that is installed or will be installed" +msgstr "" + +#. module: base +#: view:base.module.upgrade:0 +msgid "The selected modules have been updated / installed !" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Spanish (PR) / Español (PR)" +msgstr "" + +#. module: base +#: model:res.country,name:base.gt +msgid "Guatemala" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_workflow_form +#: model:ir.ui.menu,name:base.menu_low_workflow +#: model:ir.ui.menu,name:base.menu_workflow +#: model:ir.ui.menu,name:base.menu_workflow_root +msgid "Workflows" +msgstr "" + +#. module: base +#: field:ir.translation,xml_id:0 +msgid "XML Id" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_config_user_form +msgid "Create Users" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_partner_title +msgid "res.partner.title" +msgstr "" + +#. module: base +#: view:ir.values:0 +msgid "tree_but_action, client_print_multi" +msgstr "" + +#. module: base +#: model:res.partner.category,name:base.res_partner_category_retailers0 +msgid "Retailers" +msgstr "" + +#. module: base +#: help:ir.cron,priority:0 +msgid "" +"0=Very Urgent\n" +"10=Not urgent" +msgstr "" + +#. module: base +#: view:res.config:0 +#: view:res.config.installer:0 +msgid "Skip" +msgstr "" + +#. module: base +#: model:res.country,name:base.ls +msgid "Lesotho" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_model.py:114 +#, python-format +msgid "You can not remove the model '%s' !" +msgstr "" + +#. module: base +#: model:res.country,name:base.ke +msgid "Kenya" +msgstr "" + +#. module: base +#: view:res.partner.event:0 +msgid "Event" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_custom_reports +msgid "Custom Reports" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Abkhazian / аҧсуа" +msgstr "" + +#. module: base +#: view:base.module.configuration:0 +msgid "System Configuration Done" +msgstr "" + +#. module: base +#: code:addons/orm.py:929 +#, python-format +msgid "Error occurred while validating the field(s) %s: %s" +msgstr "" + +#. module: base +#: view:ir.property:0 +msgid "Generic" +msgstr "" + +#. module: base +#: model:res.country,name:base.sm +msgid "San Marino" +msgstr "" + +#. module: base +#: model:res.country,name:base.bm +msgid "Bermuda" +msgstr "" + +#. module: base +#: model:res.country,name:base.pe +msgid "Peru" +msgstr "" + +#. module: base +#: selection:ir.model.fields,on_delete:0 +msgid "Set NULL" +msgstr "" + +#. module: base +#: model:res.country,name:base.bj +msgid "Benin" +msgstr "" + +#. module: base +#: code:addons/base/publisher_warranty/publisher_warranty.py:281 +#, python-format +msgid "That contract is already registered in the system." +msgstr "" + +#. module: base +#: help:ir.sequence,suffix:0 +msgid "Suffix value of the record for the sequence" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Spanish (PY) / Español (PY)" +msgstr "" + +#. module: base +#: field:ir.config_parameter,key:0 +msgid "Key" +msgstr "" + +#. module: base +#: field:res.company,rml_header:0 +msgid "RML Header" +msgstr "" + +#. module: base +#: field:partner.sms.send,app_id:0 +msgid "API ID" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_model.py:486 +#, python-format +msgid "" +"You can not create this document (%s) ! Be sure your user belongs to one of " +"these groups: %s." +msgstr "" + +#. module: base +#: model:res.country,name:base.mu +msgid "Mauritius" +msgstr "" + +#. module: base +#: view:ir.model.access:0 +#: view:ir.rule:0 +msgid "Full Access" +msgstr "" + +#. module: base +#: view:ir.actions.act_window:0 +#: view:ir.actions.report.xml:0 +#: view:ir.actions.wizard:0 +#: view:ir.model.fields:0 +#: model:ir.ui.menu,name:base.menu_security +msgid "Security" +msgstr "" + +#. module: base +#: model:res.widget,title:base.openerp_favorites_twitter_widget +msgid "OpenERP Favorites" +msgstr "" + +#. module: base +#: model:res.country,name:base.za +msgid "South Africa" +msgstr "" + +#. module: base +#: view:ir.module.module:0 +#: selection:ir.module.module,state:0 +#: selection:ir.module.module.dependency,state:0 +msgid "Installed" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Ukrainian / українська" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_translation +#: model:ir.ui.menu,name:base.menu_action_translation +msgid "Translation Terms" +msgstr "" + +#. module: base +#: model:res.country,name:base.sn +msgid "Senegal" +msgstr "" + +#. module: base +#: model:res.country,name:base.hu +msgid "Hungary" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_groups +msgid "res.groups" +msgstr "" + +#. module: base +#: model:res.country,name:base.br +msgid "Brazil" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "%M - Minute [00,59]." +msgstr "" + +#. module: base +#: selection:ir.module.module,license:0 +msgid "Affero GPL-3" +msgstr "" + +#. module: base +#: field:ir.sequence,number_next:0 +msgid "Next Number" +msgstr "" + +#. module: base +#: help:workflow.transition,condition:0 +msgid "Expression to be satisfied if we want the transition done." +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Spanish (PA) / Español (PA)" +msgstr "" + +#. module: base +#: view:res.currency:0 +#: field:res.currency,rate_ids:0 +msgid "Rates" +msgstr "" + +#. module: base +#: model:res.country,name:base.sy +msgid "Syria" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "======================================================" +msgstr "" + +#. module: base +#: help:ir.actions.server,mobile:0 +msgid "" +"Provides fields that be used to fetch the mobile number, e.g. you select the " +"invoice, then `object.invoice_address_id.mobile` is the field which gives " +"the correct mobile number" +msgstr "" + +#. module: base +#: view:base.module.upgrade:0 +msgid "System update completed" +msgstr "" + +#. module: base +#: selection:res.request,state:0 +msgid "draft" +msgstr "" + +#. module: base +#: selection:ir.property,type:0 +#: field:res.currency,date:0 +#: field:res.currency.rate,name:0 +#: field:res.partner,date:0 +#: field:res.partner.event,date:0 +#: field:res.request,date_sent:0 +msgid "Date" +msgstr "" + +#. module: base +#: field:ir.actions.report.xml,report_sxw:0 +msgid "SXW path" +msgstr "" + +#. module: base +#: view:ir.attachment:0 +msgid "Data" +msgstr "" + +#. module: base +#: field:ir.ui.menu,parent_id:0 +#: field:wizard.ir.model.menu.create,menu_id:0 +msgid "Parent Menu" +msgstr "" + +#. module: base +#: field:ir.rule,perm_unlink:0 +msgid "Apply For Delete" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_model.py:319 +#, python-format +msgid "Cannot rename column to %s, because that column already exists!" +msgstr "" + +#. module: base +#: view:ir.attachment:0 +msgid "Attached To" +msgstr "" + +#. module: base +#: field:res.lang,decimal_point:0 +msgid "Decimal Separator" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,help:base.action_res_groups +msgid "" +"A group is a set of functional areas that will be assigned to the user in " +"order to give them access and rights to specific applications and tasks in " +"the system. You can create custom groups or edit the ones existing by " +"default in order to customize the view of the menu that users will be able " +"to see. Whether they can have a read, write, create and delete access right " +"can be managed from here." +msgstr "" + +#. module: base +#: view:res.partner:0 +#: view:res.request:0 +#: field:res.request,history:0 +msgid "History" +msgstr "" + +#. module: base +#: field:ir.attachment,create_uid:0 +msgid "Creator" +msgstr "" + +#. module: base +#: model:res.company,overdue_msg:base.main_company +msgid "" +"Please note that the following payments are now due. If your payment " +" has been sent, kindly forward your payment details. If " +"payment will be delayed further, please contact us " +"to discuss. \n" +"Would your payment have been carried out after this mail was sent, please " +"consider the present one as void." +msgstr "" + +#. module: base +#: model:res.country,name:base.mx +msgid "Mexico" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_base_config_plugins +msgid "Plugins" +msgstr "" + +#. module: base +#: field:res.company,child_ids:0 +msgid "Child Companies" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_users +msgid "res.users" +msgstr "" + +#. module: base +#: model:res.country,name:base.ni +msgid "Nicaragua" +msgstr "" + +#. module: base +#: code:addons/orm.py:1046 +#, python-format +msgid "The write method is not implemented on this object !" +msgstr "" + +#. module: base +#: view:res.partner.event:0 +msgid "General Description" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_config_simple_view_form +#: view:res.config.view:0 +msgid "Configure Your Interface" +msgstr "" + +#. module: base +#: field:ir.values,meta:0 +msgid "Meta Datas" +msgstr "" + +#. module: base +#: sql_constraint:ir.ui.view_sc:0 +msgid "Shortcut for this menu already exists!" +msgstr "" + +#. module: base +#: model:res.country,name:base.ve +msgid "Venezuela" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "9. %j ==> 340" +msgstr "" + +#. module: base +#: model:res.country,name:base.zm +msgid "Zambia" +msgstr "" + +#. module: base +#: help:res.partner,user_id:0 +msgid "" +"The internal user that is in charge of communicating with this partner if " +"any." +msgstr "" + +#. module: base +#: field:res.partner,parent_id:0 +msgid "Parent Partner" +msgstr "" + +#. module: base +#: view:ir.module.module:0 +msgid "Cancel Upgrade" +msgstr "" + +#. module: base +#: model:res.country,name:base.ci +msgid "Ivory Coast (Cote D'Ivoire)" +msgstr "" + +#. module: base +#: model:res.country,name:base.kz +msgid "Kazakhstan" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "%w - Weekday number [0(Sunday),6]." +msgstr "" + +#. module: base +#: model:ir.actions.act_window,help:base.action_partner_form +msgid "" +"A customer is an entity you do business with, like a company or an " +"organization. A customer can have several contacts or addresses which are " +"the people working for this company. You can use the history tab, to follow " +"all transactions related to a customer: sales order, emails, opportunities, " +"claims, etc. If you use the email gateway, the Outlook or the Thunderbird " +"plugin, don't forget to register emails to each contact so that the gateway " +"will automatically attach incoming emails to the right partner." +msgstr "" + +#. module: base +#: field:ir.actions.report.xml,name:0 +#: field:ir.actions.todo,name:0 +#: field:ir.cron,name:0 +#: field:ir.model.access,name:0 +#: field:ir.model.fields,name:0 +#: field:ir.module.category,name:0 +#: field:ir.module.module,name:0 +#: field:ir.module.module.dependency,name:0 +#: report:ir.module.reference.graph:0 +#: field:ir.property,name:0 +#: field:ir.rule,name:0 +#: field:ir.sequence,name:0 +#: field:ir.sequence.type,name:0 +#: field:ir.values,name:0 +#: field:multi_company.default,name:0 +#: field:res.bank,name:0 +#: field:res.config.view,name:0 +#: field:res.lang,name:0 +#: field:res.partner,name:0 +#: field:res.partner.bank.type,name:0 +#: view:res.partner.event:0 +#: field:res.request.link,name:0 +#: field:workflow,name:0 +#: field:workflow.activity,name:0 +msgid "Name" +msgstr "" + +#. module: base +#: help:ir.actions.act_window,multi:0 +msgid "" +"If set to true, the action will not be displayed on the right toolbar of a " +"form view" +msgstr "" + +#. module: base +#: model:res.country,name:base.ms +msgid "Montserrat" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_model.py:205 +#, python-format +msgid "" +"The Selection Options expression is not a valid Pythonic expression.Please " +"provide an expression in the [('key','Label'), ...] format." +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_translation_app +msgid "Application Terms" +msgstr "" + +#. module: base +#: help:res.config.users,context_tz:0 +#: help:res.users,context_tz:0 +msgid "" +"The user's timezone, used to perform timezone conversions between the server " +"and the client." +msgstr "" + +#. module: base +#: field:ir.module.module,demo:0 +msgid "Demo data" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "English (UK)" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Japanese / 日本語" +msgstr "" + +#. module: base +#: help:workflow.transition,act_from:0 +msgid "" +"Source activity. When this activity is over, the condition is tested to " +"determine if we can start the ACT_TO activity." +msgstr "" + +#. module: base +#: model:res.partner.category,name:base.res_partner_category_3 +msgid "Starter Partner" +msgstr "" + +#. module: base +#: help:ir.model.fields,relation_field:0 +msgid "" +"For one2many fields, the field on the target model that implement the " +"opposite many2one relationship" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_actions_act_window_view +msgid "ir.actions.act_window.view" +msgstr "" + +#. module: base +#: report:ir.module.reference.graph:0 +msgid "Web" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "English (CA)" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_publisher_warranty_contract +msgid "publisher_warranty.contract" +msgstr "" + +#. module: base +#: model:res.country,name:base.et +msgid "Ethiopia" +msgstr "" + +#. module: base +#: help:res.country.state,code:0 +msgid "The state code in three chars.\n" +msgstr "" + +#. module: base +#: model:res.country,name:base.sj +msgid "Svalbard and Jan Mayen Islands" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_actions_wizard +#: selection:ir.ui.menu,action:0 +msgid "ir.actions.wizard" +msgstr "" + +#. module: base +#: view:ir.actions.act_window:0 +#: view:ir.actions.report.xml:0 +#: view:ir.actions.server:0 +#: view:ir.filters:0 +#: view:res.request:0 +msgid "Group By" +msgstr "" + +#. module: base +#: view:res.config:0 +#: view:res.config.installer:0 +msgid "title" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_base_language_install +msgid "Install Language" +msgstr "" + +#. module: base +#: view:ir.translation:0 +msgid "Translation" +msgstr "" + +#. module: base +#: selection:res.request,state:0 +msgid "closed" +msgstr "" + +#. module: base +#: selection:base.language.export,state:0 +msgid "get" +msgstr "" + +#. module: base +#: help:ir.model.fields,on_delete:0 +msgid "On delete property for many2one fields" +msgstr "" + +#. module: base +#: field:ir.actions.server,write_id:0 +msgid "Write Id" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_product +msgid "Products" +msgstr "" + +#. module: base +#: field:ir.actions.act_window,domain:0 +#: field:ir.filters,domain:0 +msgid "Domain Value" +msgstr "" + +#. module: base +#: view:ir.actions.server:0 +msgid "SMS Configuration" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Spanish (BO) / Español (BO)" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.ir_access_act +#: model:ir.ui.menu,name:base.menu_ir_access_act +msgid "Access Controls List" +msgstr "" + +#. module: base +#: model:res.country,name:base.um +msgid "USA Minor Outlying Islands" +msgstr "" + +#. module: base +#: field:res.partner.bank,state:0 +#: field:res.partner.bank.type.field,bank_type_id:0 +msgid "Bank Type" +msgstr "" + +#. module: base +#: code:addons/base/res/res_user.py:58 +#: code:addons/base/res/res_user.py:67 +#, python-format +msgid "The name of the group can not start with \"-\"" +msgstr "" + +#. module: base +#: view:ir.ui.view_sc:0 +#: field:res.partner.title,shortcut:0 +msgid "Shortcut" +msgstr "" + +#. module: base +#: field:ir.model.data,date_init:0 +msgid "Init Date" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Gujarati / ગુજરાતી" +msgstr "" + +#. module: base +#: code:addons/base/module/module.py:257 +#, python-format +msgid "" +"Unable to process module \"%s\" because an external dependency is not met: %s" +msgstr "" + +#. module: base +#: view:publisher_warranty.contract.wizard:0 +msgid "Please enter the serial key provided in your contract document:" +msgstr "" + +#. module: base +#: view:workflow.activity:0 +#: field:workflow.activity,flow_start:0 +msgid "Flow Start" +msgstr "" + +#. module: base +#: code:addons/__init__.py:834 +#, python-format +msgid "module base cannot be loaded! (hint: verify addons-path)" +msgstr "" + +#. module: base +#: view:res.partner.bank:0 +msgid "Bank Account Owner" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.act_values_form +msgid "Client Actions Connections" +msgstr "" + +#. module: base +#: field:ir.attachment,res_name:0 +#: field:ir.ui.view_sc,resource:0 +msgid "Resource Name" +msgstr "" + +#. module: base +#: selection:ir.cron,interval_type:0 +msgid "Hours" +msgstr "" + +#. module: base +#: model:res.country,name:base.gp +msgid "Guadeloupe (French)" +msgstr "" + +#. module: base +#: code:addons/base/res/res_lang.py:157 +#: code:addons/base/res/res_lang.py:159 +#: code:addons/base/res/res_lang.py:161 +#, python-format +msgid "User Error" +msgstr "" + +#. module: base +#: help:workflow.transition,signal:0 +msgid "" +"When the operation of transition comes from a button pressed in the client " +"form, signal tests the name of the pressed button. If signal is NULL, no " +"button is necessary to validate this transition." +msgstr "" + +#. module: base +#: help:multi_company.default,object_id:0 +msgid "Object affected by this rule" +msgstr "" + +#. module: base +#: report:ir.module.reference.graph:0 +msgid "Directory" +msgstr "" + +#. module: base +#: field:wizard.ir.model.menu.create,name:0 +msgid "Menu Name" +msgstr "" + +#. module: base +#: view:ir.module.module:0 +msgid "Author Website" +msgstr "" + +#. module: base +#: view:ir.attachment:0 +msgid "Month" +msgstr "" + +#. module: base +#: model:res.country,name:base.my +msgid "Malaysia" +msgstr "" + +#. module: base +#: view:base.language.install:0 +#: model:ir.actions.act_window,name:base.action_view_base_language_install +msgid "Load Official Translation" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_request_history +msgid "res.request.history" +msgstr "" + +#. module: base +#: view:ir.actions.server:0 +msgid "Client Action Configuration" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_partner_address +#: view:res.partner.address:0 +msgid "Partner Addresses" +msgstr "" + +#. module: base +#: help:ir.model.fields,translate:0 +msgid "" +"Whether values for this field can be translated (enables the translation " +"mechanism for that field)" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "%S - Seconds [00,61]." +msgstr "" + +#. module: base +#: model:res.country,name:base.cv +msgid "Cape Verde" +msgstr "" + +#. module: base +#: view:base.module.import:0 +msgid "Select module package to import (.zip file):" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.act_res_partner_event +#: field:res.partner,events:0 +#: field:res.partner.event,name:0 +#: model:res.widget,title:base.events_widget +msgid "Events" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_actions_url +#: selection:ir.ui.menu,action:0 +msgid "ir.actions.url" +msgstr "" + +#. module: base +#: model:res.widget,title:base.currency_converter_widget +msgid "Currency Converter" +msgstr "" + +#. module: base +#: code:addons/orm.py:156 +#, python-format +msgid "Wrong ID for the browse record, got %r, expected an integer." +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_partner_addess_tree +#: view:res.partner:0 +msgid "Partner Contacts" +msgstr "" + +#. module: base +#: field:base.module.update,add:0 +msgid "Number of modules added" +msgstr "" + +#. module: base +#: view:res.currency:0 +msgid "Price Accuracy" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Latvian / latviešu valoda" +msgstr "" + +#. module: base +#: view:res.config:0 +#: view:res.config.installer:0 +msgid "vsep" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "French / Français" +msgstr "" + +#. module: base +#: code:addons/orm.py:1049 +#, python-format +msgid "The create method is not implemented on this object !" +msgstr "" + +#. module: base +#: field:workflow.triggers,workitem_id:0 +msgid "Workitem" +msgstr "" + +#. module: base +#: view:ir.actions.todo:0 +msgid "Set as Todo" +msgstr "" + +#. module: base +#: field:ir.actions.act_window.view,act_window_id:0 +#: view:ir.actions.actions:0 +#: field:ir.actions.todo,action_id:0 +#: field:ir.ui.menu,action:0 +#: field:ir.values,action_id:0 +#: selection:ir.values,key:0 +#: view:res.users:0 +msgid "Action" +msgstr "" + +#. module: base +#: view:ir.actions.server:0 +msgid "Email Configuration" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_cron +msgid "ir.cron" +msgstr "" + +#. module: base +#: view:ir.rule:0 +msgid "Combination of rules" +msgstr "" + +#. module: base +#: view:ir.sequence:0 +msgid "Current Year without Century: %(y)s" +msgstr "" + +#. module: base +#: field:ir.actions.server,trigger_obj_id:0 +msgid "Trigger On" +msgstr "" + +#. module: base +#: sql_constraint:ir.rule:0 +msgid "Rule must have at least one checked access right !" +msgstr "" + +#. module: base +#: model:res.country,name:base.fj +msgid "Fiji" +msgstr "" + +#. module: base +#: field:ir.model.fields,size:0 +msgid "Size" +msgstr "" + +#. module: base +#: model:res.country,name:base.sd +msgid "Sudan" +msgstr "" + +#. module: base +#: model:res.country,name:base.fm +msgid "Micronesia" +msgstr "" + +#. module: base +#: view:res.request.history:0 +msgid "Request History" +msgstr "" + +#. module: base +#: field:ir.actions.act_window,menus:0 +#: field:ir.module.module,menus_by_module:0 +#: view:res.groups:0 +msgid "Menus" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Serbian (Latin) / srpski" +msgstr "" + +#. module: base +#: model:res.country,name:base.il +msgid "Israel" +msgstr "" + +#. module: base +#: model:ir.actions.wizard,name:base.wizard_server_action_create +msgid "Create Action" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_model_model +#: model:ir.model,name:base.model_ir_model +#: model:ir.ui.menu,name:base.ir_model_model_menu +msgid "Objects" +msgstr "" + +#. module: base +#: field:res.lang,time_format:0 +msgid "Time Format" +msgstr "" + +#. module: base +#: view:ir.module.module:0 +msgid "Defined Reports" +msgstr "" + +#. module: base +#: view:ir.actions.report.xml:0 +msgid "Report xml" +msgstr "" + +#. module: base +#: field:base.language.export,modules:0 +#: model:ir.actions.act_window,name:base.action_module_open_categ +#: model:ir.actions.act_window,name:base.open_module_tree +#: view:ir.module.module:0 +#: model:ir.ui.menu,name:base.menu_management +#: model:ir.ui.menu,name:base.menu_module_tree +msgid "Modules" +msgstr "" + +#. module: base +#: view:workflow.activity:0 +#: selection:workflow.activity,kind:0 +#: field:workflow.activity,subflow_id:0 +#: field:workflow.workitem,subflow_id:0 +msgid "Subflow" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_config +msgid "res.config" +msgstr "" + +#. module: base +#: field:workflow.transition,signal:0 +msgid "Signal (button Name)" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_res_bank_form +#: model:ir.ui.menu,name:base.menu_action_res_bank_form +#: view:res.bank:0 +#: field:res.partner,bank_ids:0 +msgid "Banks" +msgstr "" + +#. module: base +#: view:res.log:0 +msgid "Unread" +msgstr "" + +#. module: base +#: field:ir.cron,doall:0 +msgid "Repeat Missed" +msgstr "" + +#. module: base +#: help:ir.actions.server,state:0 +msgid "Type of the Action that is to be executed" +msgstr "" + +#. module: base +#: field:ir.server.object.lines,server_id:0 +msgid "Object Mapping" +msgstr "" + +#. module: base +#: help:res.currency,rate:0 +#: help:res.currency.rate,rate:0 +msgid "The rate of the currency to the currency of rate 1" +msgstr "" + +#. module: base +#: model:res.country,name:base.uk +msgid "United Kingdom" +msgstr "" + +#. module: base +#: view:res.config:0 +#: view:res.config.users:0 +#: view:res.config.view:0 +msgid "res_config_contents" +msgstr "" + +#. module: base +#: help:res.partner.category,active:0 +msgid "The active field allows you to hide the category without removing it." +msgstr "" + +#. module: base +#: report:ir.module.reference.graph:0 +msgid "Object:" +msgstr "" + +#. module: base +#: model:res.country,name:base.bw +msgid "Botswana" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_partner_title_partner +#: model:ir.ui.menu,name:base.menu_partner_title_partner +#: view:res.partner.title:0 +msgid "Partner Titles" +msgstr "" + +#. module: base +#: help:ir.actions.act_window,auto_refresh:0 +msgid "Add an auto-refresh on the view" +msgstr "" + +#. module: base +#: help:res.partner,employee:0 +msgid "Check this box if the partner is an Employee." +msgstr "" + +#. module: base +#: field:ir.actions.report.xml,report_rml_content:0 +#: field:ir.actions.report.xml,report_rml_content_data:0 +msgid "RML content" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_workflow_workitem_form +#: model:ir.ui.menu,name:base.menu_workflow_workitem +msgid "Workitems" +msgstr "" + +#. module: base +#: field:base.language.export,advice:0 +msgid "Advice" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_attachment +msgid "ir.attachment" +msgstr "" + +#. module: base +#: code:addons/orm.py:3533 +#, python-format +msgid "" +"You cannot perform this operation. New Record Creation is not allowed for " +"this object as this object is for reporting purpose." +msgstr "" + +#. module: base +#: view:base.language.import:0 +msgid "- module,type,name,res_id,src,value" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Lithuanian / Lietuvių kalba" +msgstr "" + +#. module: base +#: help:ir.actions.server,record_id:0 +msgid "" +"Provide the field name where the record id is stored after the create " +"operations. If it is empty, you can not track the new record." +msgstr "" + +#. module: base +#: help:ir.model.fields,relation:0 +msgid "For relationship fields, the technical name of the target model" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Indonesian / Bahasa Indonesia" +msgstr "" + +#. module: base +#: field:ir.ui.view,inherit_id:0 +msgid "Inherited View" +msgstr "" + +#. module: base +#: view:ir.translation:0 +msgid "Source Term" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_main_pm +msgid "Project" +msgstr "" + +#. module: base +#: field:ir.ui.menu,web_icon_hover_data:0 +msgid "Web Icon Image (hover)" +msgstr "" + +#. module: base +#: view:base.module.import:0 +msgid "Module file successfully imported!" +msgstr "" + +#. module: base +#: selection:ir.actions.todo,state:0 +msgid "Cancelled" +msgstr "" + +#. module: base +#: view:res.config.users:0 +msgid "Create User" +msgstr "" + +#. module: base +#: view:partner.clear.ids:0 +msgid "Want to Clear Ids ? " +msgstr "" + +#. module: base +#: field:publisher_warranty.contract,name:0 +#: field:publisher_warranty.contract.wizard,name:0 +msgid "Serial Key" +msgstr "" + +#. module: base +#: selection:res.request,priority:0 +msgid "Low" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_audit +msgid "Audit" +msgstr "" + +#. module: base +#: model:res.country,name:base.lc +msgid "Saint Lucia" +msgstr "" + +#. module: base +#: view:publisher_warranty.contract:0 +msgid "Maintenance Contract" +msgstr "" + +#. module: base +#: help:ir.actions.server,trigger_obj_id:0 +msgid "Select the object from the model on which the workflow will executed." +msgstr "" + +#. module: base +#: field:res.partner,employee:0 +msgid "Employee" +msgstr "" + +#. module: base +#: field:ir.model.access,perm_create:0 +msgid "Create Access" +msgstr "" + +#. module: base +#: field:res.partner.address,state_id:0 +msgid "Fed. State" +msgstr "" + +#. module: base +#: field:ir.actions.server,copy_object:0 +msgid "Copy Of" +msgstr "" + +#. module: base +#: field:ir.model,osv_memory:0 +msgid "In-memory model" +msgstr "" + +#. module: base +#: view:partner.clear.ids:0 +msgid "Clear Ids" +msgstr "" + +#. module: base +#: model:res.country,name:base.io +msgid "British Indian Ocean Territory" +msgstr "" + +#. module: base +#: field:res.config.users,view:0 +#: field:res.config.view,view:0 +#: field:res.users,view:0 +msgid "Interface" +msgstr "" + +#. module: base +#: view:ir.actions.server:0 +msgid "Field Mapping" +msgstr "" + +#. module: base +#: view:publisher_warranty.contract:0 +msgid "Refresh Validation Dates" +msgstr "" + +#. module: base +#: view:ir.model:0 +#: field:ir.model.fields,ttype:0 +msgid "Field Type" +msgstr "" + +#. module: base +#: field:res.country.state,code:0 +msgid "State Code" +msgstr "" + +#. module: base +#: field:ir.model.fields,on_delete:0 +msgid "On delete" +msgstr "" + +#. module: base +#: selection:res.lang,direction:0 +msgid "Left-to-Right" +msgstr "" + +#. module: base +#: view:res.lang:0 +#: field:res.lang,translatable:0 +msgid "Translatable" +msgstr "" + +#. module: base +#: model:res.country,name:base.vn +msgid "Vietnam" +msgstr "" + +#. module: base +#: field:res.config.users,signature:0 +#: view:res.users:0 +#: field:res.users,signature:0 +msgid "Signature" +msgstr "" + +#. module: base +#: code:addons/fields.py:456 +#: code:addons/fields.py:654 +#: code:addons/fields.py:656 +#: code:addons/fields.py:658 +#: code:addons/fields.py:660 +#: code:addons/fields.py:662 +#: code:addons/fields.py:664 +#, python-format +msgid "Not Implemented" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_widget_user +msgid "res.widget.user" +msgstr "" + +#. module: base +#: field:res.partner.category,complete_name:0 +msgid "Full Name" +msgstr "" + +#. module: base +#: view:base.module.configuration:0 +msgid "_Ok" +msgstr "" + +#. module: base +#: help:ir.filters,user_id:0 +msgid "False means for every user" +msgstr "" + +#. module: base +#: code:addons/base/module/module.py:198 +#, python-format +msgid "The name of the module must be unique !" +msgstr "" + +#. module: base +#: model:res.country,name:base.mz +msgid "Mozambique" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_project_long_term +msgid "Long Term Planning" +msgstr "" + +#. module: base +#: field:ir.actions.server,message:0 +#: view:partner.sms.send:0 +#: field:partner.wizard.spam,text:0 +#: field:res.log,name:0 +msgid "Message" +msgstr "" + +#. module: base +#: field:ir.actions.act_window.view,multi:0 +msgid "On Multiple Doc." +msgstr "" + +#. module: base +#: view:res.partner:0 +#: field:res.partner,user_id:0 +msgid "Salesman" +msgstr "" + +#. module: base +#: field:res.partner,address:0 +#: view:res.partner.address:0 +msgid "Contacts" +msgstr "" + +#. module: base +#: code:addons/orm.py:3199 +#, python-format +msgid "" +"Unable to delete this document because it is used as a default property" +msgstr "" + +#. module: base +#: view:res.widget.wizard:0 +msgid "Add" +msgstr "" + +#. module: base +#: view:base.module.upgrade:0 +#: model:ir.actions.act_window,name:base.action_view_base_module_upgrade_window +#: model:ir.ui.menu,name:base.menu_view_base_module_upgrade +msgid "Apply Scheduled Upgrades" +msgstr "" + +#. module: base +#: view:res.widget:0 +msgid "Widgets" +msgstr "" + +#. module: base +#: model:res.country,name:base.cz +msgid "Czech Republic" +msgstr "" + +#. module: base +#: view:res.widget.wizard:0 +msgid "Widget Wizard" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,help:base.act_ir_actions_todo_form +msgid "" +"The configuration wizards are used to help you configure a new instance of " +"OpenERP. They are launched during the installation of new modules, but you " +"can choose to restart some wizards manually from this menu." +msgstr "" + +#. module: base +#: code:addons/base/res/res_user.py:206 +#, python-format +msgid "" +"Please use the change password wizard (in User Preferences or User menu) to " +"change your own password." +msgstr "" + +#. module: base +#: code:addons/orm.py:1350 +#, python-format +msgid "Insufficient fields for Calendar View!" +msgstr "" + +#. module: base +#: selection:ir.property,type:0 +msgid "Integer" +msgstr "" + +#. module: base +#: help:ir.actions.report.xml,report_rml:0 +msgid "" +"The path to the main report file (depending on Report Type) or NULL if the " +"content is in another data field" +msgstr "" + +#. module: base +#: help:res.config.users,company_id:0 +#: help:res.users,company_id:0 +msgid "The company this user is currently working for." +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_wizard_ir_model_menu_create +msgid "wizard.ir.model.menu.create" +msgstr "" + +#. module: base +#: view:workflow.transition:0 +msgid "Transition" +msgstr "" + +#. module: base +#: field:res.groups,menu_access:0 +msgid "Access Menu" +msgstr "" + +#. module: base +#: model:res.country,name:base.na +msgid "Namibia" +msgstr "" + +#. module: base +#: model:res.country,name:base.mn +msgid "Mongolia" +msgstr "" + +#. module: base +#: view:ir.module.module:0 +msgid "Created Menus" +msgstr "" + +#. module: base +#: selection:ir.ui.view,type:0 +msgid "mdx" +msgstr "" + +#. module: base +#: model:res.country,name:base.bi +msgid "Burundi" +msgstr "" + +#. module: base +#: view:base.language.install:0 +#: view:base.module.import:0 +#: view:base.module.update:0 +#: view:publisher_warranty.contract.wizard:0 +#: view:res.request:0 +#: wizard_button:server.action.create,init,end:0 +#: wizard_button:server.action.create,step_1,end:0 +msgid "Close" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Spanish (MX) / Español (MX)" +msgstr "" + +#. module: base +#: view:res.log:0 +msgid "My Logs" +msgstr "" + +#. module: base +#: model:res.country,name:base.bt +msgid "Bhutan" +msgstr "" + +#. module: base +#: help:ir.sequence,number_next:0 +msgid "Next number of this sequence" +msgstr "" + +#. module: base +#: model:res.partner.category,name:base.res_partner_category_11 +msgid "Textile Suppliers" +msgstr "" + +#. module: base +#: selection:ir.actions.url,target:0 +msgid "This Window" +msgstr "" + +#. module: base +#: view:publisher_warranty.contract:0 +msgid "Publisher Warranty Contracts" +msgstr "" + +#. module: base +#: help:res.log,name:0 +msgid "The logging message." +msgstr "" + +#. module: base +#: field:base.language.export,format:0 +msgid "File Format" +msgstr "" + +#. module: base +#: field:res.lang,iso_code:0 +msgid "ISO code" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_config_view +msgid "res.config.view" +msgstr "" + +#. module: base +#: view:res.log:0 +#: field:res.log,read:0 +msgid "Read" +msgstr "" + +#. module: base +#: sql_constraint:res.country:0 +msgid "The name of the country must be unique !" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,help:base.action_country_state +msgid "" +"If you are working on the American market, you can manage the different " +"federal states you are working on from here. Each state is attached to one " +"country." +msgstr "" + +#. module: base +#: view:workflow.workitem:0 +msgid "Workflow Workitems" +msgstr "" + +#. module: base +#: model:res.country,name:base.vc +msgid "Saint Vincent & Grenadines" +msgstr "" + +#. module: base +#: field:partner.sms.send,password:0 +#: field:res.config.users,password:0 +#: field:res.users,password:0 +msgid "Password" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_model_fields +#: view:ir.model:0 +#: field:ir.model,field_id:0 +#: model:ir.model,name:base.model_ir_model_fields +#: view:ir.model.fields:0 +#: model:ir.ui.menu,name:base.ir_model_model_fields +msgid "Fields" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_partner_employee_form +msgid "Employees" +msgstr "" + +#. module: base +#: help:res.log,read:0 +msgid "" +"If this log item has been read, get() should not send it to the client" +msgstr "" + +#. module: base +#: field:res.company,rml_header2:0 +#: field:res.company,rml_header3:0 +msgid "RML Internal Header" +msgstr "" + +#. module: base +#: field:ir.actions.act_window,search_view_id:0 +msgid "Search View Ref." +msgstr "" + +#. module: base +#: field:ir.module.module,installed_version:0 +msgid "Latest version" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,help:base.res_partner_canal-act +msgid "" +"Track from where is coming your leads and opportunities by creating specific " +"channels that will be maintained at the creation of a document in the " +"system. Some examples of channels can be: Website, Phone Call, Reseller, etc." +msgstr "" + +#. module: base +#: model:res.partner.bank.type.field,name:base.bank_normal_field +msgid "acc_number" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_partner_address_form +#: model:ir.ui.menu,name:base.menu_partner_address_form +msgid "Addresses" +msgstr "" + +#. module: base +#: model:res.country,name:base.mm +msgid "Myanmar" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Chinese (CN) / 简体中文" +msgstr "" + +#. module: base +#: field:res.bank,street:0 +#: field:res.partner.address,street:0 +#: field:res.partner.bank,street:0 +msgid "Street" +msgstr "" + +#. module: base +#: model:res.country,name:base.yu +msgid "Yugoslavia" +msgstr "" + +#. module: base +#: field:ir.model.data,name:0 +msgid "XML Identifier" +msgstr "" + +#. module: base +#: model:res.country,name:base.ca +msgid "Canada" +msgstr "" + +#. module: base +#: selection:ir.module.module.dependency,state:0 +msgid "Unknown" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_res_users_my +msgid "Change My Preferences" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_actions.py:164 +#, python-format +msgid "Invalid model name in the action definition." +msgstr "" + +#. module: base +#: field:partner.sms.send,text:0 +msgid "SMS Message" +msgstr "" + +#. module: base +#: model:res.country,name:base.cm +msgid "Cameroon" +msgstr "" + +#. module: base +#: model:res.country,name:base.bf +msgid "Burkina Faso" +msgstr "" + +#. module: base +#: selection:ir.actions.todo,state:0 +msgid "Skipped" +msgstr "" + +#. module: base +#: selection:ir.model.fields,state:0 +msgid "Custom Field" +msgstr "" + +#. module: base +#: field:ir.module.module,web:0 +msgid "Has a web component" +msgstr "" + +#. module: base +#: model:res.country,name:base.cc +msgid "Cocos (Keeling) Islands" +msgstr "" + +#. module: base +#: selection:base.language.install,state:0 +#: selection:base.module.import,state:0 +#: selection:base.module.update,state:0 +msgid "init" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "11. %U or %W ==> 48 (49th week)" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_partner_bank_type_field +msgid "Bank type fields" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Dutch / Nederlands" +msgstr "" + +#. module: base +#: code:addons/base/res/res_config.py:384 +#, python-format +msgid "" +"\n" +"\n" +"This addon is already installed on your system" +msgstr "" + +#. module: base +#: help:ir.cron,interval_number:0 +msgid "Repeat every x." +msgstr "" + +#. module: base +#: wizard_view:server.action.create,step_1:0 +#: wizard_field:server.action.create,step_1,report:0 +msgid "Select Report" +msgstr "" + +#. module: base +#: report:ir.module.reference.graph:0 +msgid "1cm 28cm 20cm 28cm" +msgstr "" + +#. module: base +#: field:ir.module.module,maintainer:0 +msgid "Maintainer" +msgstr "" + +#. module: base +#: field:ir.sequence,suffix:0 +msgid "Suffix" +msgstr "" + +#. module: base +#: model:res.country,name:base.mo +msgid "Macau" +msgstr "" + +#. module: base +#: model:ir.actions.report.xml,name:base.res_partner_address_report +msgid "Labels" +msgstr "" + +#. module: base +#: field:partner.wizard.spam,email_from:0 +msgid "Sender's email" +msgstr "" + +#. module: base +#: field:ir.default,field_name:0 +msgid "Object Field" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Spanish (PE) / Español (PE)" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "French (CH) / Français (CH)" +msgstr "" + +#. module: base +#: help:res.config.users,action_id:0 +#: help:res.users,action_id:0 +msgid "" +"If specified, this action will be opened at logon for this user, in addition " +"to the standard menu." +msgstr "" + +#. module: base +#: view:ir.values:0 +msgid "Client Actions" +msgstr "" + +#. module: base +#: code:addons/orm.py:1806 +#, python-format +msgid "The exists method is not implemented on this object !" +msgstr "" + +#. module: base +#: code:addons/base/module/module.py:336 +#, python-format +msgid "" +"You try to upgrade a module that depends on the module: %s.\n" +"But this module is not available in your system." +msgstr "" + +#. module: base +#: field:workflow.transition,act_to:0 +msgid "Destination Activity" +msgstr "" + +#. module: base +#: view:ir.values:0 +msgid "Connect Events to Actions" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_base_update_translations +msgid "base.update.translations" +msgstr "" + +#. module: base +#: field:ir.module.category,parent_id:0 +#: field:res.partner.category,parent_id:0 +msgid "Parent Category" +msgstr "" + +#. module: base +#: selection:ir.property,type:0 +msgid "Integer Big" +msgstr "" + +#. module: base +#: selection:res.partner.address,type:0 +#: selection:res.partner.title,domain:0 +#: view:res.users:0 +msgid "Contact" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_ui_menu +msgid "ir.ui.menu" +msgstr "" + +#. module: base +#: model:res.country,name:base.us +msgid "United States" +msgstr "" + +#. module: base +#: view:ir.module.module:0 +msgid "Cancel Uninstall" +msgstr "" + +#. module: base +#: view:res.bank:0 +#: view:res.partner:0 +#: view:res.partner.address:0 +msgid "Communication" +msgstr "" + +#. module: base +#: view:ir.actions.report.xml:0 +msgid "RML Report" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_server_object_lines +msgid "ir.server.object.lines" +msgstr "" + +#. module: base +#: code:addons/base/module/module.py:531 +#, python-format +msgid "Module %s: Invalid Quality Certificate" +msgstr "" + +#. module: base +#: model:res.country,name:base.kw +msgid "Kuwait" +msgstr "" + +#. module: base +#: field:workflow.workitem,inst_id:0 +msgid "Instance" +msgstr "" + +#. module: base +#: help:ir.actions.report.xml,attachment:0 +msgid "" +"This is the filename of the attachment used to store the printing result. " +"Keep empty to not save the printed reports. You can use a python expression " +"with the object and time variables." +msgstr "" + +#. module: base +#: selection:ir.property,type:0 +msgid "Many2One" +msgstr "" + +#. module: base +#: model:res.country,name:base.ng +msgid "Nigeria" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_model.py:250 +#, python-format +msgid "For selection fields, the Selection Options must be given!" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_partner_sms_send +msgid "SMS Send" +msgstr "" + +#. module: base +#: field:res.company,user_ids:0 +msgid "Accepted Users" +msgstr "" + +#. module: base +#: field:ir.ui.menu,web_icon_data:0 +msgid "Web Icon Image" +msgstr "" + +#. module: base +#: view:ir.values:0 +msgid "Values for Event Type" +msgstr "" + +#. module: base +#: selection:ir.model.fields,select_level:0 +msgid "Always Searchable" +msgstr "" + +#. module: base +#: model:res.country,name:base.hk +msgid "Hong Kong" +msgstr "" + +#. module: base +#: help:ir.actions.server,name:0 +msgid "Easy to Refer action by name e.g. One Sales Order -> Many Invoices" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,help:base.action_partner_address_form +msgid "" +"Customers (also called Partners in other areas of the system) helps you " +"manage your address book of companies whether they are prospects, customers " +"and/or suppliers. The partner form allows you to track and record all the " +"necessary information to interact with your partners from the company " +"address to their contacts as well as pricelists, and much more. If you " +"installed the CRM, with the history tab, you can track all the interactions " +"with a partner such as opportunities, emails, or sales orders issued." +msgstr "" + +#. module: base +#: model:res.country,name:base.ph +msgid "Philippines" +msgstr "" + +#. module: base +#: model:res.country,name:base.ma +msgid "Morocco" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "2. %a ,%A ==> Fri, Friday" +msgstr "" + +#. module: base +#: field:res.widget,content:0 +msgid "Content" +msgstr "" + +#. module: base +#: help:ir.rule,global:0 +msgid "If no group is specified the rule is global and applied to everyone" +msgstr "" + +#. module: base +#: model:res.country,name:base.td +msgid "Chad" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_workflow_transition +msgid "workflow.transition" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "%a - Abbreviated weekday name." +msgstr "" + +#. module: base +#: report:ir.module.reference.graph:0 +msgid "Introspection report on objects" +msgstr "" + +#. module: base +#: model:res.country,name:base.pf +msgid "Polynesia (French)" +msgstr "" + +#. module: base +#: model:res.country,name:base.dm +msgid "Dominica" +msgstr "" + +#. module: base +#: sql_constraint:publisher_warranty.contract:0 +msgid "" +"Your publisher warranty contract is already subscribed in the system !" +msgstr "" + +#. module: base +#: help:ir.cron,nextcall:0 +msgid "Next planned execution date for this scheduler" +msgstr "" + +#. module: base +#: help:res.config.users,view:0 +#: help:res.users,view:0 +msgid "Choose between the simplified interface and the extended one" +msgstr "" + +#. module: base +#: model:res.country,name:base.np +msgid "Nepal" +msgstr "" + +#. module: base +#: code:addons/orm.py:2307 +#, python-format +msgid "" +"Invalid value for reference field \"%s\" (last part must be a non-zero " +"integer): \"%s\"" +msgstr "" + +#. module: base +#: help:ir.cron,args:0 +msgid "Arguments to be passed to the method. e.g. (uid,)" +msgstr "" + +#. module: base +#: help:ir.ui.menu,groups_id:0 +msgid "" +"If you have groups, the visibility of this menu will be based on these " +"groups. If this field is empty, OpenERP will compute visibility based on the " +"related object's read access." +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_ui_view_custom +#: model:ir.ui.menu,name:base.menu_action_ui_view_custom +#: view:ir.ui.view.custom:0 +msgid "Customized Views" +msgstr "" + +#. module: base +#: view:partner.sms.send:0 +msgid "Bulk SMS send" +msgstr "" + +#. module: base +#: view:ir.sequence:0 +msgid "Seconde: %(sec)s" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_view_base_module_update +msgid "Update Modules List" +msgstr "" + +#. module: base +#: code:addons/base/module/module.py:255 +#, python-format +msgid "" +"Unable to upgrade module \"%s\" because an external dependency is not met: %s" +msgstr "" + +#. module: base +#: code:addons/base/res/res_user.py:257 +#, python-format +msgid "" +"Please keep in mind that documents currently displayed may not be relevant " +"after switching to another company. If you have unsaved changes, please make " +"sure to save and close all forms before switching to a different company. " +"(You can click on Cancel in the User Preferences now)" +msgstr "" + +#. module: base +#: view:ir.actions.configuration.wizard:0 +msgid "Continue" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Thai / ภาษาไทย" +msgstr "" + +#. module: base +#: code:addons/orm.py:158 +#, python-format +msgid "Object %s does not exists" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Slovenian / slovenščina" +msgstr "" + +#. module: base +#: field:ir.actions.report.xml,attachment_use:0 +msgid "Reload from Attachment" +msgstr "" + +#. module: base +#: model:res.country,name:base.bv +msgid "Bouvet Island" +msgstr "" + +#. module: base +#: field:ir.attachment,name:0 +msgid "Attachment Name" +msgstr "" + +#. module: base +#: field:base.language.export,data:0 +#: field:base.language.import,data:0 +msgid "File" +msgstr "" + +#. module: base +#: view:res.config.users:0 +msgid "Add User" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_view_base_module_upgrade_install +msgid "Module Upgrade Install" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_actions_configuration_wizard +msgid "ir.actions.configuration.wizard" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "%b - Abbreviated month name." +msgstr "" + +#. module: base +#: field:res.partner,supplier:0 +#: view:res.partner.address:0 +#: field:res.partner.address,is_supplier_add:0 +#: model:res.partner.category,name:base.res_partner_category_8 +msgid "Supplier" +msgstr "" + +#. module: base +#: view:ir.actions.server:0 +#: selection:ir.actions.server,state:0 +msgid "Multi Actions" +msgstr "" + +#. module: base +#: view:base.language.export:0 +#: view:base.language.import:0 +#: view:wizard.ir.model.menu.create:0 +msgid "_Close" +msgstr "" + +#. module: base +#: field:multi_company.default,company_dest_id:0 +msgid "Default Company" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Spanish (EC) / Español (EC)" +msgstr "" + +#. module: base +#: help:ir.ui.view,xml_id:0 +msgid "ID of the view defined in xml file" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_base_module_import +#: model:ir.ui.menu,name:base.menu_view_base_module_import +msgid "Import Module" +msgstr "" + +#. module: base +#: model:res.country,name:base.as +msgid "American Samoa" +msgstr "" + +#. module: base +#: help:ir.actions.act_window,res_model:0 +msgid "Model name of the object to open in the view window" +msgstr "" + +#. module: base +#: field:res.log,secondary:0 +msgid "Secondary Log" +msgstr "" + +#. module: base +#: field:ir.model.fields,selectable:0 +msgid "Selectable" +msgstr "" + +#. module: base +#: view:res.request.link:0 +msgid "Request Link" +msgstr "" + +#. module: base +#: view:ir.attachment:0 +#: selection:ir.attachment,type:0 +#: field:ir.module.module,url:0 +msgid "URL" +msgstr "" + +#. module: base +#: help:res.country,name:0 +msgid "The full name of the country." +msgstr "" + +#. module: base +#: selection:ir.actions.server,state:0 +msgid "Iteration" +msgstr "" + +#. module: base +#: code:addons/orm.py:3448 +#: code:addons/orm.py:3532 +#, python-format +msgid "UserError" +msgstr "" + +#. module: base +#: model:res.country,name:base.ae +msgid "United Arab Emirates" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_crm_case_job_req_main +msgid "Recruitment" +msgstr "" + +#. module: base +#: model:res.country,name:base.re +msgid "Reunion (French)" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_model.py:321 +#, python-format +msgid "" +"New column name must still start with x_ , because it is a custom field!" +msgstr "" + +#. module: base +#: view:ir.model.access:0 +#: view:ir.rule:0 +#: field:ir.rule,global:0 +msgid "Global" +msgstr "" + +#. module: base +#: model:res.country,name:base.mp +msgid "Northern Mariana Islands" +msgstr "" + +#. module: base +#: model:res.country,name:base.sb +msgid "Solomon Islands" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_model.py:490 +#: code:addons/orm.py:1897 +#: code:addons/orm.py:2972 +#: code:addons/orm.py:3165 +#: code:addons/orm.py:3365 +#: code:addons/orm.py:3817 +#, python-format +msgid "AccessError" +msgstr "" + +#. module: base +#: view:res.request:0 +msgid "Waiting" +msgstr "" + +#. module: base +#: code:addons/__init__.py:834 +#, python-format +msgid "Could not load base module" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "8. %I:%M:%S %p ==> 06:25:20 PM" +msgstr "" + +#. module: base +#: code:addons/orm.py:1803 +#, python-format +msgid "The copy method is not implemented on this object !" +msgstr "" + +#. module: base +#: field:res.log,create_date:0 +msgid "Creation Date" +msgstr "" + +#. module: base +#: view:ir.translation:0 +#: model:ir.ui.menu,name:base.menu_translation +msgid "Translations" +msgstr "" + +#. module: base +#: field:ir.sequence,padding:0 +msgid "Number padding" +msgstr "" + +#. module: base +#: view:ir.actions.report.xml:0 +msgid "Report" +msgstr "" + +#. module: base +#: model:res.country,name:base.ua +msgid "Ukraine" +msgstr "" + +#. module: base +#: model:res.country,name:base.to +msgid "Tonga" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_module_category +#: view:ir.module.category:0 +msgid "Module Category" +msgstr "" + +#. module: base +#: view:partner.wizard.ean.check:0 +msgid "Ignore" +msgstr "" + +#. module: base +#: report:ir.module.reference.graph:0 +msgid "Reference Guide" +msgstr "" + +#. module: base +#: view:ir.ui.view:0 +msgid "Architecture" +msgstr "" + +#. module: base +#: model:res.country,name:base.ml +msgid "Mali" +msgstr "" + +#. module: base +#: help:res.config.users,email:0 +#: help:res.users,email:0 +msgid "" +"If an email is provided, the user will be sent a message welcoming him.\n" +"\n" +"Warning: if \"email_from\" and \"smtp_server\" aren't configured, it won't " +"be possible to email new users." +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Flemish (BE) / Vlaams (BE)" +msgstr "" + +#. module: base +#: field:ir.cron,interval_number:0 +msgid "Interval Number" +msgstr "" + +#. module: base +#: model:res.country,name:base.tk +msgid "Tokelau" +msgstr "" + +#. module: base +#: field:ir.actions.report.xml,report_xsl:0 +msgid "XSL path" +msgstr "" + +#. module: base +#: model:res.country,name:base.bn +msgid "Brunei Darussalam" +msgstr "" + +#. module: base +#: view:ir.actions.act_window:0 +#: field:ir.actions.act_window,view_type:0 +#: field:ir.actions.act_window.view,view_mode:0 +#: field:ir.ui.view,type:0 +#: field:wizard.ir.model.menu.create.line,view_type:0 +msgid "View Type" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.next_id_2 +msgid "User Interface" +msgstr "" + +#. module: base +#: field:ir.attachment,create_date:0 +msgid "Date Created" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_actions_todo +msgid "ir.actions.todo" +msgstr "" + +#. module: base +#: code:addons/base/res/res_config.py:94 +#, python-format +msgid "Couldn't find previous ir.actions.todo" +msgstr "" + +#. module: base +#: view:ir.actions.act_window:0 +msgid "General Settings" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_administration_shortcut +msgid "Custom Shortcuts" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Vietnamese / Tiếng Việt" +msgstr "" + +#. module: base +#: model:res.country,name:base.dz +msgid "Algeria" +msgstr "" + +#. module: base +#: model:res.country,name:base.be +msgid "Belgium" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_osv_memory_autovacuum +msgid "osv_memory.autovacuum" +msgstr "" + +#. module: base +#: field:base.language.export,lang:0 +#: field:base.language.install,lang:0 +#: field:base.update.translations,lang:0 +#: field:ir.translation,lang:0 +#: field:res.config.users,context_lang:0 +#: field:res.partner,lang:0 +#: field:res.users,context_lang:0 +msgid "Language" +msgstr "" + +#. module: base +#: model:res.country,name:base.gm +msgid "Gambia" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_res_company_form +#: model:ir.model,name:base.model_res_company +#: model:ir.ui.menu,name:base.menu_action_res_company_form +#: model:ir.ui.menu,name:base.menu_res_company_global +#: view:res.company:0 +#: field:res.config.users,company_ids:0 +#: view:res.users:0 +#: field:res.users,company_ids:0 +msgid "Companies" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "%H - Hour (24-hour clock) [00,23]." +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_widget +msgid "res.widget" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_model.py:258 +#, python-format +msgid "Model %s does not exist!" +msgstr "" + +#. module: base +#: code:addons/base/res/res_lang.py:159 +#, python-format +msgid "You cannot delete the language which is User's Preferred Language !" +msgstr "" + +#. module: base +#: code:addons/fields.py:103 +#, python-format +msgid "Not implemented get_memory method !" +msgstr "" + +#. module: base +#: view:ir.actions.server:0 +#: field:ir.actions.server,code:0 +#: selection:ir.actions.server,state:0 +msgid "Python Code" +msgstr "" + +#. module: base +#: code:addons/base/module/wizard/base_module_import.py:67 +#, python-format +msgid "Can not create the module file: %s !" +msgstr "" + +#. module: base +#: model:ir.module.module,description:base.module_meta_information +msgid "The kernel of OpenERP, needed for all installation." +msgstr "" + +#. module: base +#: view:base.language.install:0 +#: view:base.module.import:0 +#: view:base.module.update:0 +#: view:base.module.upgrade:0 +#: view:base.update.translations:0 +#: view:partner.clear.ids:0 +#: view:partner.sms.send:0 +#: view:partner.wizard.spam:0 +#: view:publisher_warranty.contract.wizard:0 +#: view:res.widget.wizard:0 +msgid "Cancel" +msgstr "" + +#. module: base +#: selection:base.language.export,format:0 +msgid "PO File" +msgstr "" + +#. module: base +#: model:res.country,name:base.nt +msgid "Neutral Zone" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Hindi / हिंदी" +msgstr "" + +#. module: base +#: view:ir.model:0 +msgid "Custom" +msgstr "" + +#. module: base +#: view:res.request:0 +msgid "Current" +msgstr "" + +#. module: base +#: model:res.partner.category,name:base.res_partner_category_9 +msgid "Components Supplier" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_res_users +#: field:ir.default,uid:0 +#: model:ir.ui.menu,name:base.menu_action_res_users +#: model:ir.ui.menu,name:base.menu_users +#: view:res.groups:0 +#: field:res.groups,users:0 +#: view:res.users:0 +msgid "Users" +msgstr "" + +#. module: base +#: field:ir.module.module,published_version:0 +msgid "Published Version" +msgstr "" + +#. module: base +#: model:res.country,name:base.is +msgid "Iceland" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.ir_action_window +#: model:ir.ui.menu,name:base.menu_ir_action_window +msgid "Window Actions" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "%I - Hour (12-hour clock) [01,12]." +msgstr "" + +#. module: base +#: selection:publisher_warranty.contract.wizard,state:0 +msgid "Finished" +msgstr "" + +#. module: base +#: model:res.country,name:base.de +msgid "Germany" +msgstr "" + +#. module: base +#: view:ir.sequence:0 +msgid "Week of the year: %(woy)s" +msgstr "" + +#. module: base +#: model:res.partner.category,name:base.res_partner_category_14 +msgid "Bad customers" +msgstr "" + +#. module: base +#: report:ir.module.reference.graph:0 +msgid "Reports :" +msgstr "" + +#. module: base +#: model:res.country,name:base.gy +msgid "Guyana" +msgstr "" + +#. module: base +#: help:ir.actions.act_window,view_type:0 +msgid "" +"View type: set to 'tree' for a hierarchical tree view, or 'form' for other " +"views" +msgstr "" + +#. module: base +#: code:addons/base/res/res_config.py:421 +#, python-format +msgid "Click 'Continue' to configure the next addon..." +msgstr "" + +#. module: base +#: field:ir.actions.server,record_id:0 +msgid "Create Id" +msgstr "" + +#. module: base +#: model:res.country,name:base.hn +msgid "Honduras" +msgstr "" + +#. module: base +#: help:res.config.users,menu_tips:0 +#: help:res.users,menu_tips:0 +msgid "" +"Check out this box if you want to always display tips on each menu action" +msgstr "" + +#. module: base +#: model:res.country,name:base.eg +msgid "Egypt" +msgstr "" + +#. module: base +#: field:ir.rule,perm_read:0 +msgid "Apply For Read" +msgstr "" + +#. module: base +#: help:ir.actions.server,model_id:0 +msgid "" +"Select the object on which the action will work (read, write, create)." +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_actions.py:629 +#, python-format +msgid "Please specify server option --email-from !" +msgstr "" + +#. module: base +#: field:base.language.import,name:0 +msgid "Language Name" +msgstr "" + +#. module: base +#: selection:ir.property,type:0 +msgid "Boolean" +msgstr "" + +#. module: base +#: view:ir.model:0 +msgid "Fields Description" +msgstr "" + +#. module: base +#: view:ir.attachment:0 +#: view:ir.cron:0 +#: view:ir.model.access:0 +#: view:ir.model.data:0 +#: view:ir.model.fields:0 +#: view:ir.module.module:0 +#: view:ir.rule:0 +#: view:ir.ui.view:0 +#: view:ir.values:0 +#: view:res.partner:0 +#: view:res.partner.address:0 +#: view:workflow.activity:0 +msgid "Group By..." +msgstr "" + +#. module: base +#: view:ir.model.fields:0 +#: field:ir.model.fields,readonly:0 +#: field:res.partner.bank.type.field,readonly:0 +msgid "Readonly" +msgstr "" + +#. module: base +#: field:ir.actions.act_window.view,view_id:0 +#: field:ir.default,page:0 +#: selection:ir.translation,type:0 +#: field:wizard.ir.model.menu.create.line,view_id:0 +msgid "View" +msgstr "" + +#. module: base +#: selection:ir.module.module,state:0 +#: selection:ir.module.module.dependency,state:0 +msgid "To be installed" +msgstr "" + +#. module: base +#: help:ir.actions.act_window,display_menu_tip:0 +msgid "" +"It gives the status if the tip has to be displayed or not when a user " +"executes an action" +msgstr "" + +#. module: base +#: view:ir.model:0 +#: model:ir.module.module,shortdesc:base.module_meta_information +#: field:res.currency,base:0 +msgid "Base" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Telugu / తెలుగు" +msgstr "" + +#. module: base +#: model:res.country,name:base.lr +msgid "Liberia" +msgstr "" + +#. module: base +#: view:ir.attachment:0 +#: view:ir.model:0 +#: view:res.groups:0 +#: view:res.partner:0 +#: field:res.partner,comment:0 +#: model:res.widget,title:base.note_widget +msgid "Notes" +msgstr "" + +#. module: base +#: field:ir.config_parameter,value:0 +#: field:ir.property,value_binary:0 +#: field:ir.property,value_datetime:0 +#: field:ir.property,value_float:0 +#: field:ir.property,value_integer:0 +#: field:ir.property,value_reference:0 +#: field:ir.property,value_text:0 +#: selection:ir.server.object.lines,type:0 +#: field:ir.server.object.lines,value:0 +#: view:ir.values:0 +#: field:ir.values,value:0 +#: field:ir.values,value_unpickle:0 +msgid "Value" +msgstr "" + +#. module: base +#: field:ir.sequence,code:0 +#: field:ir.sequence.type,code:0 +#: selection:ir.translation,type:0 +#: field:res.bank,code:0 +#: field:res.partner.bank.type,code:0 +msgid "Code" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_config_installer +msgid "res.config.installer" +msgstr "" + +#. module: base +#: model:res.country,name:base.mc +msgid "Monaco" +msgstr "" + +#. module: base +#: selection:ir.cron,interval_type:0 +msgid "Minutes" +msgstr "" + +#. module: base +#: selection:ir.translation,type:0 +msgid "Help" +msgstr "" + +#. module: base +#: help:res.config.users,menu_id:0 +#: help:res.users,menu_id:0 +msgid "" +"If specified, the action will replace the standard menu for this user." +msgstr "" + +#. module: base +#: selection:ir.actions.server,state:0 +msgid "Write Object" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_fundrising +msgid "Fund Raising" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.ir_sequence_type +#: model:ir.ui.menu,name:base.menu_ir_sequence_type +msgid "Sequence Codes" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Spanish (CO) / Español (CO)" +msgstr "" + +#. module: base +#: view:base.module.configuration:0 +msgid "" +"All pending configuration wizards have been executed. You may restart " +"individual wizards via the list of configuration wizards." +msgstr "" + +#. module: base +#: wizard_button:server.action.create,step_1,create:0 +msgid "Create" +msgstr "" + +#. module: base +#: view:ir.sequence:0 +msgid "Current Year with Century: %(year)s" +msgstr "" + +#. module: base +#: field:ir.exports,export_fields:0 +msgid "Export ID" +msgstr "" + +#. module: base +#: model:res.country,name:base.fr +msgid "France" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_log +msgid "res.log" +msgstr "" + +#. module: base +#: help:ir.translation,module:0 +#: help:ir.translation,xml_id:0 +msgid "Maps to the ir_model_data for which this translation is provided." +msgstr "" + +#. module: base +#: view:workflow.activity:0 +#: field:workflow.activity,flow_stop:0 +msgid "Flow Stop" +msgstr "" + +#. module: base +#: selection:ir.cron,interval_type:0 +msgid "Weeks" +msgstr "" + +#. module: base +#: model:res.country,name:base.af +msgid "Afghanistan, Islamic State of" +msgstr "" + +#. module: base +#: code:addons/base/module/wizard/base_module_import.py:67 +#, python-format +msgid "Error !" +msgstr "" + +#. module: base +#: model:res.partner.bank.type.field,name:base.bank_normal_field_contry +msgid "country_id" +msgstr "" + +#. module: base +#: field:ir.cron,interval_type:0 +msgid "Interval Unit" +msgstr "" + +#. module: base +#: field:publisher_warranty.contract,kind:0 +#: field:workflow.activity,kind:0 +msgid "Kind" +msgstr "" + +#. module: base +#: code:addons/orm.py:3775 +#, python-format +msgid "This method does not exist anymore" +msgstr "" + +#. module: base +#: field:res.bank,fax:0 +#: field:res.partner.address,fax:0 +msgid "Fax" +msgstr "" + +#. module: base +#: field:res.lang,thousands_sep:0 +msgid "Thousands Separator" +msgstr "" + +#. module: base +#: field:res.request,create_date:0 +msgid "Created Date" +msgstr "" + +#. module: base +#: help:ir.actions.server,loop_action:0 +msgid "" +"Select the action that will be executed. Loop action will not be avaliable " +"inside loop." +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Chinese (TW) / 正體字" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_request +msgid "res.request" +msgstr "" + +#. module: base +#: view:ir.model:0 +msgid "In Memory" +msgstr "" + +#. module: base +#: view:ir.actions.todo:0 +msgid "Todo" +msgstr "" + +#. module: base +#: field:ir.attachment,datas:0 +msgid "File Content" +msgstr "" + +#. module: base +#: model:res.country,name:base.pa +msgid "Panama" +msgstr "" + +#. module: base +#: model:res.partner.title,name:base.res_partner_title_ltd +msgid "Ltd" +msgstr "" + +#. module: base +#: help:workflow.transition,group_id:0 +msgid "" +"The group that a user must have to be authorized to validate this transition." +msgstr "" + +#. module: base +#: constraint:res.config.users:0 +#: constraint:res.users:0 +msgid "The chosen company is not in the allowed companies for this user" +msgstr "" + +#. module: base +#: model:res.country,name:base.gi +msgid "Gibraltar" +msgstr "" + +#. module: base +#: field:ir.actions.report.xml,report_name:0 +msgid "Service Name" +msgstr "" + +#. module: base +#: model:res.country,name:base.pn +msgid "Pitcairn Island" +msgstr "" + +#. module: base +#: view:base.module.upgrade:0 +msgid "" +"We suggest to reload the menu tab to see the new menus (Ctrl+T then Ctrl+R)." +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_rule +#: model:ir.ui.menu,name:base.menu_action_rule +msgid "Record Rules" +msgstr "" + +#. module: base +#: field:res.config.users,name:0 +#: field:res.users,name:0 +msgid "User Name" +msgstr "" + +#. module: base +#: view:ir.sequence:0 +msgid "Day of the year: %(doy)s" +msgstr "" + +#. module: base +#: view:ir.model:0 +#: view:ir.model.fields:0 +#: view:workflow.activity:0 +msgid "Properties" +msgstr "" + +#. module: base +#: help:ir.sequence,padding:0 +msgid "" +"OpenERP will automatically adds some '0' on the left of the 'Next Number' to " +"get the required padding size." +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "%A - Full weekday name." +msgstr "" + +#. module: base +#: selection:ir.cron,interval_type:0 +msgid "Months" +msgstr "" + +#. module: base +#: field:ir.actions.act_window,search_view:0 +msgid "Search View" +msgstr "" + +#. module: base +#: sql_constraint:res.lang:0 +msgid "The code of the language must be unique !" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_attachment +#: view:ir.actions.report.xml:0 +#: view:ir.attachment:0 +#: model:ir.ui.menu,name:base.menu_action_attachment +msgid "Attachments" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_base_partner +#: model:ir.ui.menu,name:base.menu_sale_config_sales +#: model:ir.ui.menu,name:base.menu_sales +msgid "Sales" +msgstr "" + +#. module: base +#: field:ir.actions.server,child_ids:0 +msgid "Other Actions" +msgstr "" + +#. module: base +#: selection:ir.actions.todo,state:0 +#: view:res.config.users:0 +msgid "Done" +msgstr "" + +#. module: base +#: model:res.partner.title,name:base.res_partner_title_miss +msgid "Miss" +msgstr "" + +#. module: base +#: view:ir.model.access:0 +#: field:ir.model.access,perm_write:0 +#: view:ir.rule:0 +msgid "Write Access" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "%m - Month number [01,12]." +msgstr "" + +#. module: base +#: field:res.bank,city:0 +#: field:res.partner,city:0 +#: field:res.partner.address,city:0 +#: field:res.partner.bank,city:0 +msgid "City" +msgstr "" + +#. module: base +#: model:res.country,name:base.qa +msgid "Qatar" +msgstr "" + +#. module: base +#: model:res.country,name:base.it +msgid "Italy" +msgstr "" + +#. module: base +#: view:ir.actions.todo:0 +#: selection:ir.actions.todo,state:0 +msgid "To Do" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Estonian / Eesti keel" +msgstr "" + +#. module: base +#: field:res.config.users,email:0 +#: field:res.partner,email:0 +#: field:res.users,email:0 +msgid "E-mail" +msgstr "" + +#. module: base +#: selection:ir.module.module,license:0 +msgid "GPL-3 or later version" +msgstr "" + +#. module: base +#: field:workflow.activity,action:0 +msgid "Python Action" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "English (US)" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_model_data +#: view:ir.model.data:0 +#: model:ir.ui.menu,name:base.ir_model_data_menu +msgid "Object Identifiers" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,help:base.action_partner_title_partner +msgid "" +"Manage the partner titles you want to have available in your system. The " +"partner titles is the legal status of the company: Private Limited, SA, etc." +msgstr "" + +#. module: base +#: view:base.language.export:0 +msgid "To browse official translations, you can start with these links:" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_model.py:484 +#, python-format +msgid "" +"You can not read this document (%s) ! Be sure your user belongs to one of " +"these groups: %s." +msgstr "" + +#. module: base +#: view:res.bank:0 +#: field:res.config.users,address_id:0 +#: view:res.partner.address:0 +#: view:res.users:0 +#: field:res.users,address_id:0 +msgid "Address" +msgstr "" + +#. module: base +#: field:ir.module.module,latest_version:0 +msgid "Installed version" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Mongolian / монгол" +msgstr "" + +#. module: base +#: model:res.country,name:base.mr +msgid "Mauritania" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_translation +msgid "ir.translation" +msgstr "" + +#. module: base +#: view:base.module.update:0 +msgid "Module update result" +msgstr "" + +#. module: base +#: view:workflow.activity:0 +#: field:workflow.workitem,act_id:0 +msgid "Activity" +msgstr "" + +#. module: base +#: view:res.partner:0 +#: view:res.partner.address:0 +msgid "Postal Address" +msgstr "" + +#. module: base +#: field:res.company,parent_id:0 +msgid "Parent Company" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Spanish (CR) / Español (CR)" +msgstr "" + +#. module: base +#: field:res.currency.rate,rate:0 +msgid "Rate" +msgstr "" + +#. module: base +#: model:res.country,name:base.cg +msgid "Congo" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "Examples" +msgstr "" + +#. module: base +#: field:ir.default,value:0 +msgid "Default Value" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_tools +msgid "Tools" +msgstr "" + +#. module: base +#: model:res.country,name:base.kn +msgid "Saint Kitts & Nevis Anguilla" +msgstr "" + +#. module: base +#: code:addons/base/res/res_currency.py:100 +#, python-format +msgid "" +"No rate found \n" +"for the currency: %s \n" +"at the date: %s" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,help:base.action_ui_view_custom +msgid "" +"Customized views are used when users reorganize the content of their " +"dashboard views (via web client)" +msgstr "" + +#. module: base +#: field:ir.model,name:0 +#: field:ir.model.fields,model:0 +#: field:ir.values,model:0 +msgid "Object Name" +msgstr "" + +#. module: base +#: help:ir.actions.server,srcmodel_id:0 +msgid "" +"Object in which you want to create / write the object. If it is empty then " +"refer to the Object field." +msgstr "" + +#. module: base +#: view:ir.module.module:0 +#: selection:ir.module.module,state:0 +#: selection:ir.module.module.dependency,state:0 +msgid "Not Installed" +msgstr "" + +#. module: base +#: view:workflow.activity:0 +#: field:workflow.activity,out_transitions:0 +msgid "Outgoing Transitions" +msgstr "" + +#. module: base +#: field:ir.ui.menu,icon:0 +msgid "Icon" +msgstr "" + +#. module: base +#: help:ir.model.fields,model_id:0 +msgid "The model this field belongs to" +msgstr "" + +#. module: base +#: model:res.country,name:base.mq +msgid "Martinique (French)" +msgstr "" + +#. module: base +#: view:ir.sequence.type:0 +msgid "Sequences Type" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.res_request-act +#: model:ir.ui.menu,name:base.menu_res_request_act +#: model:ir.ui.menu,name:base.menu_resquest_ref +#: view:res.request:0 +msgid "Requests" +msgstr "" + +#. module: base +#: model:res.country,name:base.ye +msgid "Yemen" +msgstr "" + +#. module: base +#: selection:workflow.activity,split_mode:0 +msgid "Or" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.res_log_act_window +#: model:ir.ui.menu,name:base.menu_res_log_act_window +msgid "Client Logs" +msgstr "" + +#. module: base +#: model:res.country,name:base.al +msgid "Albania" +msgstr "" + +#. module: base +#: model:res.country,name:base.ws +msgid "Samoa" +msgstr "" + +#. module: base +#: code:addons/base/res/res_lang.py:161 +#, python-format +msgid "" +"You cannot delete the language which is Active !\n" +"Please de-activate the language first." +msgstr "" + +#. module: base +#: view:base.language.install:0 +#: view:base.module.import:0 +msgid "" +"Please be patient, this operation may take a few minutes (depending on the " +"number of modules currently installed)..." +msgstr "" + +#. module: base +#: field:ir.ui.menu,child_id:0 +msgid "Child IDs" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_actions.py:713 +#: code:addons/base/ir/ir_actions.py:716 +#, python-format +msgid "Problem in configuration `Record Id` in Server Action!" +msgstr "" + +#. module: base +#: code:addons/orm.py:2306 +#: code:addons/orm.py:2316 +#, python-format +msgid "ValidateError" +msgstr "" + +#. module: base +#: view:base.module.import:0 +#: view:base.module.update:0 +msgid "Open Modules" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,help:base.action_res_bank_form +msgid "Manage bank records you want to be used in the system." +msgstr "" + +#. module: base +#: view:base.module.import:0 +msgid "Import module" +msgstr "" + +#. module: base +#: field:ir.actions.server,loop_action:0 +msgid "Loop Action" +msgstr "" + +#. module: base +#: help:ir.actions.report.xml,report_file:0 +msgid "" +"The path to the main report file (depending on Report Type) or NULL if the " +"content is in another field" +msgstr "" + +#. module: base +#: model:res.country,name:base.la +msgid "Laos" +msgstr "" + +#. module: base +#: selection:ir.actions.server,state:0 +#: field:res.config.users,user_email:0 +#: field:res.users,user_email:0 +msgid "Email" +msgstr "" + +#. module: base +#: field:res.config.users,action_id:0 +#: field:res.users,action_id:0 +msgid "Home Action" +msgstr "" + +#. module: base +#: code:addons/custom.py:558 +#, python-format +msgid "" +"The sum of the data (2nd field) is null.\n" +"We can't draw a pie chart !" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_lunch_reporting +#: model:ir.ui.menu,name:base.menu_project_report +#: model:ir.ui.menu,name:base.menu_report_association +#: model:ir.ui.menu,name:base.menu_report_marketing +#: model:ir.ui.menu,name:base.menu_reporting +#: model:ir.ui.menu,name:base.next_id_64 +#: model:ir.ui.menu,name:base.next_id_73 +#: model:ir.ui.menu,name:base.reporting_menu +msgid "Reporting" +msgstr "" + +#. module: base +#: model:res.country,name:base.tg +msgid "Togo" +msgstr "" + +#. module: base +#: selection:ir.module.module,license:0 +msgid "Other Proprietary" +msgstr "" + +#. module: base +#: selection:workflow.activity,kind:0 +msgid "Stop All" +msgstr "" + +#. module: base +#: code:addons/orm.py:412 +#, python-format +msgid "The read_group method is not implemented on this object !" +msgstr "" + +#. module: base +#: view:ir.model.data:0 +msgid "Updatable" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "3. %x ,%X ==> 12/05/08, 18:25:20" +msgstr "" + +#. module: base +#: selection:ir.model.fields,on_delete:0 +msgid "Cascade" +msgstr "" + +#. module: base +#: field:workflow.transition,group_id:0 +msgid "Group Required" +msgstr "" + +#. module: base +#: view:ir.actions.configuration.wizard:0 +msgid "Next Configuration Step" +msgstr "" + +#. module: base +#: field:res.groups,comment:0 +msgid "Comment" +msgstr "" + +#. module: base +#: model:res.country,name:base.ro +msgid "Romania" +msgstr "" + +#. module: base +#: help:ir.cron,doall:0 +msgid "" +"Enable this if you want to execute missed occurences as soon as the server " +"restarts." +msgstr "" + +#. module: base +#: view:base.module.upgrade:0 +msgid "Start update" +msgstr "" + +#. module: base +#: code:addons/base/publisher_warranty/publisher_warranty.py:144 +#, python-format +msgid "Contract validation error" +msgstr "" + +#. module: base +#: field:res.country.state,name:0 +msgid "State Name" +msgstr "" + +#. module: base +#: field:workflow.activity,join_mode:0 +msgid "Join Mode" +msgstr "" + +#. module: base +#: field:res.config.users,context_tz:0 +#: field:res.users,context_tz:0 +msgid "Timezone" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_actions_report_xml +#: selection:ir.ui.menu,action:0 +msgid "ir.actions.report.xml" +msgstr "" + +#. module: base +#: model:res.partner.title,shortcut:base.res_partner_title_miss +msgid "Mss" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_ui_view +msgid "ir.ui.view" +msgstr "" + +#. module: base +#: constraint:res.partner:0 +msgid "Error ! You can not create recursive associated members." +msgstr "" + +#. module: base +#: help:res.lang,code:0 +msgid "This field is used to set/get locales for user" +msgstr "" + +#. module: base +#: model:res.partner.category,name:base.res_partner_category_2 +msgid "OpenERP Partners" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_hr_manager +msgid "HR Manager Dashboard" +msgstr "" + +#. module: base +#: code:addons/base/module/module.py:253 +#, python-format +msgid "" +"Unable to install module \"%s\" because an external dependency is not met: %s" +msgstr "" + +#. module: base +#: view:ir.module.module:0 +msgid "Search modules" +msgstr "" + +#. module: base +#: model:res.country,name:base.by +msgid "Belarus" +msgstr "" + +#. module: base +#: field:ir.actions.act_window,name:0 +#: field:ir.actions.act_window_close,name:0 +#: field:ir.actions.actions,name:0 +#: field:ir.actions.server,name:0 +#: field:ir.actions.url,name:0 +#: field:ir.filters,name:0 +msgid "Action Name" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,help:base.action_res_users +msgid "" +"Create and manage users that will connect to the system. Users can be " +"deactivated should there be a period of time during which they will/should " +"not connect to the system. You can assign them groups in order to give them " +"specific access to the applications they need to use in the system." +msgstr "" + +#. module: base +#: selection:res.request,priority:0 +msgid "Normal" +msgstr "" + +#. module: base +#: field:res.bank,street2:0 +#: field:res.partner.address,street2:0 +msgid "Street2" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_view_base_module_update +msgid "Module Update" +msgstr "" + +#. module: base +#: code:addons/base/module/wizard/base_module_upgrade.py:95 +#, python-format +msgid "Following modules are not installed or unknown: %s" +msgstr "" + +#. module: base +#: view:ir.cron:0 +#: field:ir.cron,user_id:0 +#: view:ir.filters:0 +#: field:ir.filters,user_id:0 +#: field:ir.ui.view.custom,user_id:0 +#: field:ir.values,user_id:0 +#: field:res.log,user_id:0 +#: field:res.partner.event,user_id:0 +#: view:res.users:0 +#: field:res.widget.user,user_id:0 +msgid "User" +msgstr "" + +#. module: base +#: model:res.country,name:base.pr +msgid "Puerto Rico" +msgstr "" + +#. module: base +#: view:ir.actions.act_window:0 +msgid "Open Window" +msgstr "" + +#. module: base +#: field:ir.actions.act_window,auto_search:0 +msgid "Auto Search" +msgstr "" + +#. module: base +#: field:ir.actions.act_window,filter:0 +msgid "Filter" +msgstr "" + +#. module: base +#: model:res.partner.title,shortcut:base.res_partner_title_madam +msgid "Ms." +msgstr "" + +#. module: base +#: model:res.country,name:base.ch +msgid "Switzerland" +msgstr "" + +#. module: base +#: model:res.country,name:base.gd +msgid "Grenada" +msgstr "" + +#. module: base +#: model:res.country,name:base.wf +msgid "Wallis and Futuna Islands" +msgstr "" + +#. module: base +#: selection:server.action.create,init,type:0 +msgid "Open Report" +msgstr "" + +#. module: base +#: field:res.currency,rounding:0 +msgid "Rounding factor" +msgstr "" + +#. module: base +#: view:base.language.install:0 +msgid "Load" +msgstr "" + +#. module: base +#: help:res.config.users,name:0 +#: help:res.users,name:0 +msgid "The new user's real name, used for searching and most listings" +msgstr "" + +#. module: base +#: code:addons/osv.py:154 +#: code:addons/osv.py:156 +#, python-format +msgid "Integrity Error" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_wizard_screen +msgid "ir.wizard.screen" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_model.py:223 +#, python-format +msgid "Size of the field can never be less than 1 !" +msgstr "" + +#. module: base +#: model:res.country,name:base.so +msgid "Somalia" +msgstr "" + +#. module: base +#: selection:publisher_warranty.contract,state:0 +msgid "Terminated" +msgstr "" + +#. module: base +#: model:res.partner.category,name:base.res_partner_category_13 +msgid "Important customers" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "Update Terms" +msgstr "" + +#. module: base +#: field:partner.sms.send,mobile_to:0 +#: field:res.request,act_to:0 +#: field:res.request.history,act_to:0 +msgid "To" +msgstr "" + +#. module: base +#: view:ir.cron:0 +#: field:ir.cron,args:0 +msgid "Arguments" +msgstr "" + +#. module: base +#: code:addons/orm.py:716 +#, python-format +msgid "Database ID doesn't exist: %s : %s" +msgstr "" + +#. module: base +#: selection:ir.module.module,license:0 +msgid "GPL Version 2" +msgstr "" + +#. module: base +#: selection:ir.module.module,license:0 +msgid "GPL Version 3" +msgstr "" + +#. module: base +#: code:addons/orm.py:836 +#, python-format +msgid "key '%s' not found in selection field '%s'" +msgstr "" + +#. module: base +#: view:partner.wizard.ean.check:0 +msgid "Correct EAN13" +msgstr "" + +#. module: base +#: code:addons/orm.py:2317 +#, python-format +msgid "The value \"%s\" for the field \"%s\" is not in the selection" +msgstr "" + +#. module: base +#: field:res.partner,customer:0 +#: view:res.partner.address:0 +#: field:res.partner.address,is_customer_add:0 +#: model:res.partner.category,name:base.res_partner_category_0 +msgid "Customer" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Spanish (NI) / Español (NI)" +msgstr "" + +#. module: base +#: field:ir.module.module,shortdesc:0 +msgid "Short Description" +msgstr "" + +#. module: base +#: field:ir.actions.act_window,context:0 +#: field:ir.filters,context:0 +msgid "Context Value" +msgstr "" + +#. module: base +#: view:ir.sequence:0 +msgid "Hour 00->24: %(h24)s" +msgstr "" + +#. module: base +#: field:ir.cron,nextcall:0 +msgid "Next Execution Date" +msgstr "" + +#. module: base +#: help:multi_company.default,field_id:0 +msgid "Select field property" +msgstr "" + +#. module: base +#: field:res.request.history,date_sent:0 +msgid "Date sent" +msgstr "" + +#. module: base +#: view:ir.sequence:0 +msgid "Month: %(month)s" +msgstr "" + +#. module: base +#: field:ir.actions.act_window.view,sequence:0 +#: field:ir.actions.server,sequence:0 +#: field:ir.actions.todo,sequence:0 +#: view:ir.cron:0 +#: view:ir.sequence:0 +#: field:ir.ui.menu,sequence:0 +#: view:ir.ui.view:0 +#: field:ir.ui.view,priority:0 +#: field:ir.ui.view_sc,sequence:0 +#: field:multi_company.default,sequence:0 +#: field:res.partner.bank,sequence:0 +#: field:res.widget.user,sequence:0 +#: field:wizard.ir.model.menu.create.line,sequence:0 +msgid "Sequence" +msgstr "" + +#. module: base +#: model:res.country,name:base.tn +msgid "Tunisia" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_mrp_root +msgid "Manufacturing" +msgstr "" + +#. module: base +#: model:res.country,name:base.km +msgid "Comoros" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_server_action +#: view:ir.actions.server:0 +#: model:ir.ui.menu,name:base.menu_server_action +msgid "Server Actions" +msgstr "" + +#. module: base +#: view:ir.module.module:0 +msgid "Cancel Install" +msgstr "" + +#. module: base +#: field:ir.model.fields,selection:0 +msgid "Selection Options" +msgstr "" + +#. module: base +#: field:res.partner.category,parent_right:0 +msgid "Right parent" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "Legends for Date and Time Formats" +msgstr "" + +#. module: base +#: selection:ir.actions.server,state:0 +msgid "Copy Object" +msgstr "" + +#. module: base +#: code:addons/base/res/res_user.py:581 +#, python-format +msgid "" +"Group(s) cannot be deleted, because some user(s) still belong to them: %s !" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_country_state +#: model:ir.ui.menu,name:base.menu_country_state_partner +msgid "Fed. States" +msgstr "" + +#. module: base +#: view:ir.model:0 +#: view:res.groups:0 +msgid "Access Rules" +msgstr "" + +#. module: base +#: field:ir.default,ref_table:0 +msgid "Table Ref." +msgstr "" + +#. module: base +#: field:ir.actions.act_window,res_model:0 +#: field:ir.actions.report.xml,model:0 +#: field:ir.actions.server,model_id:0 +#: field:ir.actions.wizard,model:0 +#: field:ir.cron,model:0 +#: field:ir.default,field_tbl:0 +#: field:ir.filters,model_id:0 +#: field:ir.model,model:0 +#: view:ir.model.access:0 +#: field:ir.model.access,model_id:0 +#: view:ir.model.data:0 +#: field:ir.model.data,model:0 +#: view:ir.model.fields:0 +#: view:ir.rule:0 +#: field:ir.rule,model_id:0 +#: selection:ir.translation,type:0 +#: view:ir.ui.view:0 +#: field:ir.ui.view,model:0 +#: view:ir.values:0 +#: field:ir.values,model_id:0 +#: field:multi_company.default,object_id:0 +#: field:res.log,res_model:0 +#: field:res.request.link,object:0 +#: field:workflow.triggers,model:0 +msgid "Object" +msgstr "" + +#. module: base +#: code:addons/osv.py:151 +#, python-format +msgid "" +"\n" +"\n" +"[object with reference: %s - %s]" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_default +msgid "ir.default" +msgstr "" + +#. module: base +#: view:ir.sequence:0 +msgid "Minute: %(min)s" +msgstr "" + +#. module: base +#: view:base.update.translations:0 +#: model:ir.actions.act_window,name:base.action_wizard_update_translations +#: model:ir.ui.menu,name:base.menu_wizard_update_translations +msgid "Synchronize Translations" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.next_id_10 +msgid "Scheduler" +msgstr "" + +#. module: base +#: help:ir.cron,numbercall:0 +msgid "" +"Number of time the function is called,\n" +"a negative number indicates no limit" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_model.py:331 +#, python-format +msgid "" +"Changing the type of a column is not yet supported. Please drop it and " +"create it again!" +msgstr "" + +#. module: base +#: field:ir.ui.view_sc,user_id:0 +msgid "User Ref." +msgstr "" + +#. module: base +#: code:addons/base/res/res_user.py:580 +#, python-format +msgid "Warning !" +msgstr "" + +#. module: base +#: model:res.widget,title:base.google_maps_widget +msgid "Google Maps" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_base_config +#: model:ir.ui.menu,name:base.menu_config +#: model:ir.ui.menu,name:base.menu_event_config +#: model:ir.ui.menu,name:base.menu_lunch_survey_root +#: model:ir.ui.menu,name:base.menu_marketing_config_association +#: model:ir.ui.menu,name:base.menu_marketing_config_root +#: view:res.company:0 +msgid "Configuration" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_publisher_warranty_contract_wizard +msgid "publisher_warranty.contract.wizard" +msgstr "" + +#. module: base +#: field:ir.actions.server,expression:0 +msgid "Loop Expression" +msgstr "" + +#. module: base +#: field:publisher_warranty.contract,date_start:0 +msgid "Starting Date" +msgstr "" + +#. module: base +#: help:res.partner,website:0 +msgid "Website of Partner" +msgstr "" + +#. module: base +#: model:res.partner.category,name:base.res_partner_category_5 +msgid "Gold Partner" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_partner +#: field:res.company,partner_id:0 +#: view:res.partner.address:0 +#: field:res.partner.bank,partner_id:0 +#: field:res.partner.event,partner_id:0 +#: selection:res.partner.title,domain:0 +#: model:res.request.link,name:base.req_link_partner +msgid "Partner" +msgstr "" + +#. module: base +#: model:res.country,name:base.tr +msgid "Turkey" +msgstr "" + +#. module: base +#: model:res.country,name:base.fk +msgid "Falkland Islands" +msgstr "" + +#. module: base +#: model:res.country,name:base.lb +msgid "Lebanon" +msgstr "" + +#. module: base +#: view:ir.actions.report.xml:0 +#: field:ir.actions.report.xml,report_type:0 +msgid "Report Type" +msgstr "" + +#. module: base +#: field:ir.actions.todo,state:0 +#: view:ir.module.module:0 +#: field:ir.module.module,state:0 +#: field:ir.module.module.dependency,state:0 +#: field:publisher_warranty.contract,state:0 +#: field:res.bank,state:0 +#: view:res.country.state:0 +#: field:res.partner.bank,state_id:0 +#: view:res.request:0 +#: field:res.request,state:0 +#: field:workflow.instance,state:0 +#: field:workflow.workitem,state:0 +msgid "State" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Galician / Galego" +msgstr "" + +#. module: base +#: model:res.country,name:base.no +msgid "Norway" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "4. %b, %B ==> Dec, December" +msgstr "" + +#. module: base +#: view:base.language.install:0 +#: model:ir.ui.menu,name:base.menu_view_base_language_install +msgid "Load an Official Translation" +msgstr "" + +#. module: base +#: view:res.currency:0 +msgid "Miscelleanous" +msgstr "" + +#. module: base +#: model:res.partner.category,name:base.res_partner_category_10 +msgid "Open Source Service Company" +msgstr "" + +#. module: base +#: model:res.country,name:base.kg +msgid "Kyrgyz Republic (Kyrgyzstan)" +msgstr "" + +#. module: base +#: selection:res.request,state:0 +msgid "waiting" +msgstr "" + +#. module: base +#: field:ir.actions.report.xml,report_file:0 +msgid "Report file" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_workflow_triggers +msgid "workflow.triggers" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_model.py:62 +#, python-format +msgid "Invalid search criterions" +msgstr "" + +#. module: base +#: view:ir.attachment:0 +msgid "Created" +msgstr "" + +#. module: base +#: help:ir.actions.wizard,multi:0 +msgid "" +"If set to true, the wizard will not be displayed on the right toolbar of a " +"form view." +msgstr "" + +#. module: base +#: view:base.language.import:0 +msgid "- type,name,res_id,src,value" +msgstr "" + +#. module: base +#: model:res.country,name:base.hm +msgid "Heard and McDonald Islands" +msgstr "" + +#. module: base +#: field:ir.actions.act_window,view_id:0 +msgid "View Ref." +msgstr "" + +#. module: base +#: selection:ir.translation,type:0 +msgid "Selection" +msgstr "" + +#. module: base +#: field:res.company,rml_header1:0 +msgid "Report Header" +msgstr "" + +#. module: base +#: field:ir.actions.act_window,type:0 +#: field:ir.actions.act_window_close,type:0 +#: field:ir.actions.actions,type:0 +#: field:ir.actions.report.xml,type:0 +#: view:ir.actions.server:0 +#: field:ir.actions.server,state:0 +#: field:ir.actions.server,type:0 +#: field:ir.actions.url,type:0 +#: field:ir.actions.wizard,type:0 +msgid "Action Type" +msgstr "" + +#. module: base +#: code:addons/base/module/module.py:268 +#, python-format +msgid "" +"You try to install module '%s' that depends on module '%s'.\n" +"But the latter module is not available in your system." +msgstr "" + +#. module: base +#: view:base.language.import:0 +#: model:ir.actions.act_window,name:base.action_view_base_import_language +#: model:ir.ui.menu,name:base.menu_view_base_import_language +msgid "Import Translation" +msgstr "" + +#. module: base +#: field:res.partner.bank.type,field_ids:0 +msgid "Type fields" +msgstr "" + +#. module: base +#: view:ir.module.module:0 +#: field:ir.module.module,category_id:0 +msgid "Category" +msgstr "" + +#. module: base +#: view:ir.attachment:0 +#: selection:ir.attachment,type:0 +#: selection:ir.property,type:0 +msgid "Binary" +msgstr "" + +#. module: base +#: field:ir.actions.server,sms:0 +#: selection:ir.actions.server,state:0 +msgid "SMS" +msgstr "" + +#. module: base +#: model:res.country,name:base.cr +msgid "Costa Rica" +msgstr "" + +#. module: base +#: view:workflow.activity:0 +msgid "Conditions" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_partner_other_form +msgid "Other Partners" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_currency_form +#: model:ir.ui.menu,name:base.menu_action_currency_form +#: view:res.currency:0 +msgid "Currencies" +msgstr "" + +#. module: base +#: sql_constraint:res.groups:0 +msgid "The name of the group must be unique !" +msgstr "" + +#. module: base +#: view:ir.sequence:0 +msgid "Hour 00->12: %(h12)s" +msgstr "" + +#. module: base +#: help:res.partner.address,active:0 +msgid "Uncheck the active field to hide the contact." +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_widget_wizard +msgid "Add a widget for User" +msgstr "" + +#. module: base +#: model:res.country,name:base.dk +msgid "Denmark" +msgstr "" + +#. module: base +#: field:res.country,code:0 +msgid "Country Code" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_workflow_instance +msgid "workflow.instance" +msgstr "" + +#. module: base +#: code:addons/orm.py:278 +#, python-format +msgid "Unknown attribute %s in %s " +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "10. %S ==> 20" +msgstr "" + +#. module: base +#: code:addons/fields.py:106 +#, python-format +msgid "undefined get method !" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Norwegian Bokmål / Norsk bokmål" +msgstr "" + +#. module: base +#: help:res.config.users,new_password:0 +#: help:res.users,new_password:0 +msgid "" +"Only specify a value if you want to change the user password. This user will " +"have to logout and login again!" +msgstr "" + +#. module: base +#: model:res.partner.title,name:base.res_partner_title_madam +msgid "Madam" +msgstr "" + +#. module: base +#: model:res.country,name:base.ee +msgid "Estonia" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.dashboard +msgid "Dashboards" +msgstr "" + +#. module: base +#: help:ir.attachment,type:0 +msgid "Binary File or external URL" +msgstr "" + +#. module: base +#: field:res.config.users,new_password:0 +#: field:res.users,new_password:0 +msgid "Change password" +msgstr "" + +#. module: base +#: model:res.country,name:base.nl +msgid "Netherlands" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.next_id_4 +msgid "Low Level Objects" +msgstr "" + +#. module: base +#: view:res.company:0 +msgid "Your Logo - Use a size of about 450x150 pixels." +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_values +msgid "ir.values" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Occitan (FR, post 1500) / Occitan" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,help:base.open_module_tree +msgid "" +"You can install new modules in order to activate new features, menu, reports " +"or data in your OpenERP instance. To install some modules, click on the " +"button \"Schedule for Installation\" from the form view, then click on " +"\"Apply Scheduled Upgrades\" to migrate your system." +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_emails +#: model:ir.ui.menu,name:base.menu_mail_gateway +msgid "Emails" +msgstr "" + +#. module: base +#: model:res.country,name:base.cd +msgid "Congo, The Democratic Republic of the" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Malayalam / മലയാളം" +msgstr "" + +#. module: base +#: view:res.request:0 +#: field:res.request,body:0 +#: field:res.request.history,req_id:0 +msgid "Request" +msgstr "" + +#. module: base +#: model:res.country,name:base.jp +msgid "Japan" +msgstr "" + +#. module: base +#: field:ir.cron,numbercall:0 +msgid "Number of Calls" +msgstr "" + +#. module: base +#: view:base.module.upgrade:0 +#: field:base.module.upgrade,module_info:0 +msgid "Modules to update" +msgstr "" + +#. module: base +#: help:ir.actions.server,sequence:0 +msgid "" +"Important when you deal with multiple actions, the execution order will be " +"decided based on this, low number is higher priority." +msgstr "" + +#. module: base +#: field:ir.actions.report.xml,header:0 +msgid "Add RML header" +msgstr "" + +#. module: base +#: model:res.country,name:base.gr +msgid "Greece" +msgstr "" + +#. module: base +#: field:res.request,trigger_date:0 +msgid "Trigger Date" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Croatian / hrvatski jezik" +msgstr "" + +#. module: base +#: field:base.language.install,overwrite:0 +msgid "Overwrite Existing Terms" +msgstr "" + +#. module: base +#: help:ir.actions.server,code:0 +msgid "Python code to be executed" +msgstr "" + +#. module: base +#: sql_constraint:res.country:0 +msgid "The code of the country must be unique !" +msgstr "" + +#. module: base +#: selection:ir.module.module.dependency,state:0 +msgid "Uninstallable" +msgstr "" + +#. module: base +#: view:res.partner.category:0 +msgid "Partner Category" +msgstr "" + +#. module: base +#: view:ir.actions.server:0 +#: selection:ir.actions.server,state:0 +msgid "Trigger" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_base_module_update +msgid "Update Module" +msgstr "" + +#. module: base +#: view:ir.model.fields:0 +#: field:ir.model.fields,translate:0 +msgid "Translate" +msgstr "" + +#. module: base +#: field:res.request.history,body:0 +msgid "Body" +msgstr "" + +#. module: base +#: view:partner.wizard.spam:0 +msgid "Send Email" +msgstr "" + +#. module: base +#: field:res.config.users,menu_id:0 +#: field:res.users,menu_id:0 +msgid "Menu Action" +msgstr "" + +#. module: base +#: help:ir.model.fields,selection:0 +msgid "" +"List of options for a selection field, specified as a Python expression " +"defining a list of (key, label) pairs. For example: " +"[('blue','Blue'),('yellow','Yellow')]" +msgstr "" + +#. module: base +#: selection:base.language.export,state:0 +msgid "choose" +msgstr "" + +#. module: base +#: help:ir.model,osv_memory:0 +msgid "" +"Indicates whether this object model lives in memory only, i.e. is not " +"persisted (osv.osv_memory)" +msgstr "" + +#. module: base +#: field:res.partner,child_ids:0 +#: field:res.request,ref_partner_id:0 +msgid "Partner Ref." +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_partner_supplier_form +#: model:ir.ui.menu,name:base.menu_procurement_management_supplier_name +#: view:res.partner:0 +msgid "Suppliers" +msgstr "" + +#. module: base +#: view:publisher_warranty.contract.wizard:0 +msgid "Register" +msgstr "" + +#. module: base +#: field:res.request,ref_doc2:0 +msgid "Document Ref 2" +msgstr "" + +#. module: base +#: field:res.request,ref_doc1:0 +msgid "Document Ref 1" +msgstr "" + +#. module: base +#: model:res.country,name:base.ga +msgid "Gabon" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_model_data +msgid "ir.model.data" +msgstr "" + +#. module: base +#: view:ir.model:0 +#: view:ir.rule:0 +#: view:res.groups:0 +msgid "Access Rights" +msgstr "" + +#. module: base +#: model:res.country,name:base.gl +msgid "Greenland" +msgstr "" + +#. module: base +#: field:res.partner.bank,acc_number:0 +msgid "Account Number" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "1. %c ==> Fri Dec 5 18:25:20 2008" +msgstr "" + +#. module: base +#: model:res.country,name:base.nc +msgid "New Caledonia (French)" +msgstr "" + +#. module: base +#: model:res.country,name:base.cy +msgid "Cyprus" +msgstr "" + +#. module: base +#: view:base.module.import:0 +msgid "" +"This wizard helps you add a new language to you OpenERP system. After " +"loading a new language it becomes available as default interface language " +"for users and partners." +msgstr "" + +#. module: base +#: field:ir.actions.server,subject:0 +#: field:partner.wizard.spam,subject:0 +#: field:res.request,name:0 +msgid "Subject" +msgstr "" + +#. module: base +#: field:res.request,act_from:0 +#: field:res.request.history,act_from:0 +msgid "From" +msgstr "" + +#. module: base +#: view:res.users:0 +msgid "Preferences" +msgstr "" + +#. module: base +#: model:res.partner.category,name:base.res_partner_category_consumers0 +msgid "Consumers" +msgstr "" + +#. module: base +#: view:res.config:0 +#: wizard_button:server.action.create,init,step_1:0 +msgid "Next" +msgstr "" + +#. module: base +#: help:ir.cron,function:0 +msgid "" +"Name of the method to be called on the object when this scheduler is " +"executed." +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_model.py:219 +#, python-format +msgid "" +"The Selection Options expression is must be in the [('key','Label'), ...] " +"format!" +msgstr "" + +#. module: base +#: view:ir.actions.report.xml:0 +msgid "Miscellaneous" +msgstr "" + +#. module: base +#: model:res.country,name:base.cn +msgid "China" +msgstr "" + +#. module: base +#: code:addons/base/res/res_user.py:516 +#, python-format +msgid "" +"--\n" +"%(name)s %(email)s\n" +msgstr "" + +#. module: base +#: model:res.country,name:base.eh +msgid "Western Sahara" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_workflow +msgid "workflow" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,help:base.action_res_company_form +msgid "" +"Create and manage the companies that will be managed by OpenERP from here. " +"Shops or subsidiaries can be created and maintained from here." +msgstr "" + +#. module: base +#: model:res.country,name:base.id +msgid "Indonesia" +msgstr "" + +#. module: base +#: view:base.update.translations:0 +msgid "" +"This wizard will detect new terms to translate in the application, so that " +"you can then add translations manually or perform a complete export (as a " +"template for a new language example)." +msgstr "" + +#. module: base +#: help:multi_company.default,expression:0 +msgid "" +"Expression, must be True to match\n" +"use context.get or user (browse)" +msgstr "" + +#. module: base +#: model:res.country,name:base.bg +msgid "Bulgaria" +msgstr "" + +#. module: base +#: view:publisher_warranty.contract.wizard:0 +msgid "Publisher warranty contract successfully registered!" +msgstr "" + +#. module: base +#: model:res.country,name:base.ao +msgid "Angola" +msgstr "" + +#. module: base +#: model:res.country,name:base.tf +msgid "French Southern Territories" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_currency +#: field:res.company,currency_id:0 +#: field:res.company,currency_ids:0 +#: view:res.currency:0 +#: field:res.currency,name:0 +#: field:res.currency.rate,currency_id:0 +msgid "Currency" +msgstr "" + +#. module: base +#: field:res.partner.canal,name:0 +msgid "Channel Name" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "5. %y, %Y ==> 08, 2008" +msgstr "" + +#. module: base +#: model:res.partner.title,shortcut:base.res_partner_title_ltd +msgid "ltd" +msgstr "" + +#. module: base +#: field:ir.values,res_id:0 +#: field:res.log,res_id:0 +msgid "Object ID" +msgstr "" + +#. module: base +#: view:res.company:0 +msgid "Landscape" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_administration +msgid "Administration" +msgstr "" + +#. module: base +#: view:base.module.update:0 +msgid "Click on Update below to start the process..." +msgstr "" + +#. module: base +#: model:res.country,name:base.ir +msgid "Iran" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.res_widget_user_act_window +#: model:ir.ui.menu,name:base.menu_res_widget_user_act_window +msgid "Widgets per User" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Slovak / Slovenský jazyk" +msgstr "" + +#. module: base +#: field:base.language.export,state:0 +#: field:ir.ui.menu,icon_pict:0 +#: field:publisher_warranty.contract.wizard,state:0 +msgid "unknown" +msgstr "" + +#. module: base +#: field:res.currency,symbol:0 +msgid "Symbol" +msgstr "" + +#. module: base +#: help:res.config.users,login:0 +#: help:res.users,login:0 +msgid "Used to log into the system" +msgstr "" + +#. module: base +#: view:base.update.translations:0 +msgid "Synchronize Translation" +msgstr "" + +#. module: base +#: field:ir.ui.view_sc,res_id:0 +msgid "Resource Ref." +msgstr "" + +#. module: base +#: model:res.country,name:base.ki +msgid "Kiribati" +msgstr "" + +#. module: base +#: model:res.country,name:base.iq +msgid "Iraq" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_association +msgid "Association" +msgstr "" + +#. module: base +#: model:res.country,name:base.cl +msgid "Chile" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_address_book +#: model:ir.ui.menu,name:base.menu_config_address_book +#: model:ir.ui.menu,name:base.menu_procurement_management_supplier +msgid "Address Book" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_sequence_type +msgid "ir.sequence.type" +msgstr "" + +#. module: base +#: selection:base.language.export,format:0 +msgid "CSV File" +msgstr "" + +#. module: base +#: field:res.company,account_no:0 +msgid "Account No." +msgstr "" + +#. module: base +#: code:addons/base/res/res_lang.py:157 +#, python-format +msgid "Base Language 'en_US' can not be deleted !" +msgstr "" + +#. module: base +#: selection:ir.model,state:0 +msgid "Base Object" +msgstr "" + +#. module: base +#: report:ir.module.reference.graph:0 +msgid "Dependencies :" +msgstr "" + +#. module: base +#: field:ir.model.fields,field_description:0 +msgid "Field Label" +msgstr "" + +#. module: base +#: model:res.country,name:base.dj +msgid "Djibouti" +msgstr "" + +#. module: base +#: field:ir.translation,value:0 +msgid "Translation Value" +msgstr "" + +#. module: base +#: model:res.country,name:base.ag +msgid "Antigua and Barbuda" +msgstr "" + +#. module: base +#: code:addons/orm.py:3166 +#, python-format +msgid "" +"Operation prohibited by access rules, or performed on an already deleted " +"document (Operation: %s, Document type: %s)." +msgstr "" + +#. module: base +#: model:res.country,name:base.zr +msgid "Zaire" +msgstr "" + +#. module: base +#: field:ir.model.data,res_id:0 +#: field:ir.translation,res_id:0 +#: field:workflow.instance,res_id:0 +#: field:workflow.triggers,res_id:0 +msgid "Resource ID" +msgstr "" + +#. module: base +#: view:ir.cron:0 +#: field:ir.model,info:0 +msgid "Information" +msgstr "" + +#. module: base +#: view:res.widget.user:0 +msgid "User Widgets" +msgstr "" + +#. module: base +#: view:base.module.update:0 +msgid "Update Module List" +msgstr "" + +#. module: base +#: selection:res.partner.address,type:0 +msgid "Other" +msgstr "" + +#. module: base +#: view:res.request:0 +msgid "Reply" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Turkish / Türkçe" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_workflow_activity_form +#: model:ir.ui.menu,name:base.menu_workflow_activity +#: view:workflow:0 +#: field:workflow,activities:0 +msgid "Activities" +msgstr "" + +#. module: base +#: field:ir.actions.act_window,auto_refresh:0 +msgid "Auto-Refresh" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_model.py:62 +#, python-format +msgid "The osv_memory field can only be compared with = and != operator." +msgstr "" + +#. module: base +#: selection:ir.ui.view,type:0 +msgid "Diagram" +msgstr "" + +#. module: base +#: help:multi_company.default,name:0 +msgid "Name it to easily find a record" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.grant_menu_access +#: model:ir.ui.menu,name:base.menu_grant_menu_access +msgid "Menu Items" +msgstr "" + +#. module: base +#: constraint:ir.rule:0 +msgid "Rules are not supported for osv_memory objects !" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_event_association +#: model:ir.ui.menu,name:base.menu_event_main +msgid "Events Organisation" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.ir_sequence_actions +#: model:ir.ui.menu,name:base.menu_custom_action +#: model:ir.ui.menu,name:base.menu_ir_sequence_actions +#: model:ir.ui.menu,name:base.next_id_6 +#: view:workflow.activity:0 +msgid "Actions" +msgstr "" + +#. module: base +#: selection:res.request,priority:0 +msgid "High" +msgstr "" + +#. module: base +#: field:ir.exports.line,export_id:0 +msgid "Export" +msgstr "" + +#. module: base +#: model:res.country,name:base.hr +msgid "Croatia" +msgstr "" + +#. module: base +#: help:res.bank,bic:0 +msgid "Bank Identifier Code" +msgstr "" + +#. module: base +#: model:res.country,name:base.tm +msgid "Turkmenistan" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_actions.py:597 +#: code:addons/base/ir/ir_actions.py:629 +#: code:addons/base/ir/ir_actions.py:713 +#: code:addons/base/ir/ir_actions.py:716 +#: code:addons/base/ir/ir_model.py:114 +#: code:addons/base/ir/ir_model.py:204 +#: code:addons/base/ir/ir_model.py:218 +#: code:addons/base/ir/ir_model.py:232 +#: code:addons/base/ir/ir_model.py:250 +#: code:addons/base/ir/ir_model.py:255 +#: code:addons/base/ir/ir_model.py:258 +#: code:addons/base/module/module.py:215 +#: code:addons/base/module/module.py:258 +#: code:addons/base/module/module.py:262 +#: code:addons/base/module/module.py:268 +#: code:addons/base/module/module.py:303 +#: code:addons/base/module/module.py:321 +#: code:addons/base/module/module.py:336 +#: code:addons/base/module/module.py:429 +#: code:addons/base/module/module.py:531 +#: code:addons/base/publisher_warranty/publisher_warranty.py:163 +#: code:addons/base/publisher_warranty/publisher_warranty.py:281 +#: code:addons/base/res/res_currency.py:100 +#: code:addons/base/res/res_user.py:57 +#: code:addons/base/res/res_user.py:66 +#: code:addons/custom.py:558 +#: code:addons/orm.py:3199 +#, python-format +msgid "Error" +msgstr "" + +#. module: base +#: model:res.country,name:base.pm +msgid "Saint Pierre and Miquelon" +msgstr "" + +#. module: base +#: help:ir.actions.report.xml,header:0 +msgid "Add or not the coporate RML header" +msgstr "" + +#. module: base +#: help:workflow.transition,act_to:0 +msgid "The destination activity." +msgstr "" + +#. module: base +#: view:base.module.update:0 +#: view:base.update.translations:0 +msgid "Update" +msgstr "" + +#. module: base +#: model:ir.actions.report.xml,name:base.ir_module_reference_print +msgid "Technical guide" +msgstr "" + +#. module: base +#: model:res.country,name:base.tz +msgid "Tanzania" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Danish / Dansk" +msgstr "" + +#. module: base +#: selection:ir.model.fields,select_level:0 +msgid "Advanced Search (deprecated)" +msgstr "" + +#. module: base +#: model:res.country,name:base.cx +msgid "Christmas Island" +msgstr "" + +#. module: base +#: view:ir.actions.server:0 +msgid "Other Actions Configuration" +msgstr "" + +#. module: base +#: view:res.config.installer:0 +msgid "Install Modules" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.res_partner_canal-act +#: model:ir.model,name:base.model_res_partner_canal +#: model:ir.ui.menu,name:base.menu_res_partner_canal-act +#: view:res.partner.canal:0 +msgid "Channels" +msgstr "" + +#. module: base +#: view:ir.ui.view:0 +msgid "Extra Info" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.act_values_form_action +#: model:ir.ui.menu,name:base.menu_values_form_action +msgid "Client Events" +msgstr "" + +#. module: base +#: view:ir.module.module:0 +msgid "Schedule for Installation" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_partner_wizard_ean_check +msgid "Ean Check" +msgstr "" + +#. module: base +#: sql_constraint:res.config.users:0 +#: sql_constraint:res.users:0 +msgid "You can not have two users with the same login !" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_multi_company_default +msgid "Default multi company" +msgstr "" + +#. module: base +#: view:res.request:0 +msgid "Send" +msgstr "" + +#. module: base +#: field:res.config.users,menu_tips:0 +#: field:res.users,menu_tips:0 +msgid "Menu Tips" +msgstr "" + +#. module: base +#: field:ir.translation,src:0 +msgid "Source" +msgstr "" + +#. module: base +#: help:res.partner.address,partner_id:0 +msgid "Keep empty for a private address, not related to partner." +msgstr "" + +#. module: base +#: model:res.country,name:base.vu +msgid "Vanuatu" +msgstr "" + +#. module: base +#: view:res.company:0 +msgid "Internal Header/Footer" +msgstr "" + +#. module: base +#: code:addons/base/module/wizard/base_export_language.py:59 +#, python-format +msgid "" +"Save this document to a .tgz file. This archive containt UTF-8 %s files and " +"may be uploaded to launchpad." +msgstr "" + +#. module: base +#: view:base.module.upgrade:0 +msgid "Start configuration" +msgstr "" + +#. module: base +#: view:base.language.export:0 +msgid "_Export" +msgstr "" + +#. module: base +#: field:base.language.install,state:0 +#: field:base.module.import,state:0 +#: field:base.module.update,state:0 +msgid "state" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Catalan / Català" +msgstr "" + +#. module: base +#: model:res.country,name:base.do +msgid "Dominican Republic" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Serbian (Cyrillic) / српски" +msgstr "" + +#. module: base +#: code:addons/orm.py:2161 +#, python-format +msgid "" +"Invalid group_by specification: \"%s\".\n" +"A group_by specification must be a list of valid fields." +msgstr "" + +#. module: base +#: model:res.country,name:base.sa +msgid "Saudi Arabia" +msgstr "" + +#. module: base +#: help:res.partner,supplier:0 +msgid "" +"Check this box if the partner is a supplier. If it's not checked, purchase " +"people will not see it when encoding a purchase order." +msgstr "" + +#. module: base +#: field:ir.model.fields,relation_field:0 +msgid "Relation Field" +msgstr "" + +#. module: base +#: view:res.partner.event:0 +msgid "Event Logs" +msgstr "" + +#. module: base +#: code:addons/base/module/wizard/base_module_configuration.py:37 +#, python-format +msgid "System Configuration done" +msgstr "" + +#. module: base +#: field:workflow.triggers,instance_id:0 +msgid "Destination Instance" +msgstr "" + +#. module: base +#: field:ir.actions.act_window,multi:0 +#: field:ir.actions.wizard,multi:0 +msgid "Action on Multiple Doc." +msgstr "" + +#. module: base +#: view:base.language.export:0 +msgid "https://translations.launchpad.net/openobject" +msgstr "" + +#. module: base +#: field:ir.actions.report.xml,report_xml:0 +msgid "XML path" +msgstr "" + +#. module: base +#: selection:ir.actions.todo,restart:0 +msgid "On Skip" +msgstr "" + +#. module: base +#: model:res.country,name:base.gn +msgid "Guinea" +msgstr "" + +#. module: base +#: model:res.country,name:base.lu +msgid "Luxembourg" +msgstr "" + +#. module: base +#: help:ir.values,key2:0 +msgid "" +"The kind of action or button in the client side that will trigger the action." +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_ui_menu.py:285 +#, python-format +msgid "Error ! You can not create recursive Menu." +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_publisher_warranty_contract_add_wizard +#: model:ir.ui.menu,name:base.menu_publisher_warranty_contract_add +#: view:publisher_warranty.contract.wizard:0 +msgid "Register a Contract" +msgstr "" + +#. module: base +#: view:ir.rule:0 +msgid "" +"3. If user belongs to several groups, the results from step 2 are combined " +"with logical OR operator" +msgstr "" + +#. module: base +#: code:addons/base/publisher_warranty/publisher_warranty.py:145 +#, python-format +msgid "Please check your publisher warranty contract name and validity." +msgstr "" + +#. module: base +#: model:res.country,name:base.sv +msgid "El Salvador" +msgstr "" + +#. module: base +#: field:res.bank,phone:0 +#: field:res.partner,phone:0 +#: field:res.partner.address,phone:0 +msgid "Phone" +msgstr "" + +#. module: base +#: field:ir.cron,active:0 +#: field:ir.sequence,active:0 +#: field:res.bank,active:0 +#: field:res.config.users,active:0 +#: field:res.currency,active:0 +#: field:res.lang,active:0 +#: field:res.partner,active:0 +#: field:res.partner.address,active:0 +#: field:res.partner.canal,active:0 +#: field:res.partner.category,active:0 +#: field:res.request,active:0 +#: field:res.users,active:0 +#: view:workflow.instance:0 +#: view:workflow.workitem:0 +msgid "Active" +msgstr "" + +#. module: base +#: model:res.country,name:base.th +msgid "Thailand" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_crm_config_lead +msgid "Leads & Opportunities" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Romanian / română" +msgstr "" + +#. module: base +#: view:res.log:0 +msgid "System Logs" +msgstr "" + +#. module: base +#: selection:workflow.activity,join_mode:0 +#: selection:workflow.activity,split_mode:0 +msgid "And" +msgstr "" + +#. module: base +#: field:ir.model.fields,relation:0 +msgid "Object Relation" +msgstr "" + +#. module: base +#: view:ir.rule:0 +#: view:res.partner:0 +msgid "General" +msgstr "" + +#. module: base +#: model:res.country,name:base.uz +msgid "Uzbekistan" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_actions_act_window +#: selection:ir.ui.menu,action:0 +msgid "ir.actions.act_window" +msgstr "" + +#. module: base +#: field:ir.rule,perm_create:0 +msgid "Apply For Create" +msgstr "" + +#. module: base +#: model:res.country,name:base.vi +msgid "Virgin Islands (USA)" +msgstr "" + +#. module: base +#: model:res.country,name:base.tw +msgid "Taiwan" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_currency_rate +msgid "Currency Rate" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,help:base.grant_menu_access +msgid "" +"Manage and customize the items available and displayed in your OpenERP " +"system menu. You can delete an item by clicking on the box at the beginning " +"of each line and then delete it through the button that appeared. Items can " +"be assigned to specific groups in order to make them accessible to some " +"users within the system." +msgstr "" + +#. module: base +#: field:ir.ui.view,field_parent:0 +msgid "Child Field" +msgstr "" + +#. module: base +#: field:ir.actions.act_window,usage:0 +#: field:ir.actions.act_window_close,usage:0 +#: field:ir.actions.actions,usage:0 +#: field:ir.actions.report.xml,usage:0 +#: field:ir.actions.server,usage:0 +#: field:ir.actions.wizard,usage:0 +msgid "Action Usage" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_workflow_workitem +msgid "workflow.workitem" +msgstr "" + +#. module: base +#: selection:ir.module.module,state:0 +msgid "Not Installable" +msgstr "" + +#. module: base +#: report:ir.module.reference.graph:0 +msgid "View :" +msgstr "" + +#. module: base +#: field:ir.model.fields,view_load:0 +msgid "View Auto-Load" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_model.py:232 +#, python-format +msgid "You cannot remove the field '%s' !" +msgstr "" + +#. module: base +#: field:ir.exports,resource:0 +#: view:ir.property:0 +#: field:ir.property,res_id:0 +msgid "Resource" +msgstr "" + +#. module: base +#: field:ir.ui.menu,web_icon:0 +msgid "Web Icon File" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Persian / فارس" +msgstr "" + +#. module: base +#: view:ir.actions.act_window:0 +msgid "View Ordering" +msgstr "" + +#. module: base +#: code:addons/base/module/wizard/base_module_upgrade.py:95 +#, python-format +msgid "Unmet dependency !" +msgstr "" + +#. module: base +#: view:base.language.import:0 +msgid "" +"Supported file formats: *.csv (Comma-separated values) or *.po (GetText " +"Portable Objects)" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_model.py:487 +#, python-format +msgid "" +"You can not delete this document (%s) ! Be sure your user belongs to one of " +"these groups: %s." +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_base_module_configuration +msgid "base.module.configuration" +msgstr "" + +#. module: base +#: field:base.language.export,name:0 +#: field:ir.attachment,datas_fname:0 +msgid "Filename" +msgstr "" + +#. module: base +#: field:ir.model,access_ids:0 +#: view:ir.model.access:0 +msgid "Access" +msgstr "" + +#. module: base +#: model:res.country,name:base.sk +msgid "Slovak Republic" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.publisher_warranty +msgid "Publisher Warranty" +msgstr "" + +#. module: base +#: model:res.country,name:base.aw +msgid "Aruba" +msgstr "" + +#. module: base +#: model:res.country,name:base.ar +msgid "Argentina" +msgstr "" + +#. module: base +#: field:res.groups,name:0 +msgid "Group Name" +msgstr "" + +#. module: base +#: model:res.country,name:base.bh +msgid "Bahrain" +msgstr "" + +#. module: base +#: model:res.partner.category,name:base.res_partner_category_12 +msgid "Segmentation" +msgstr "" + +#. module: base +#: view:ir.attachment:0 +#: field:ir.attachment,company_id:0 +#: field:ir.default,company_id:0 +#: field:ir.property,company_id:0 +#: field:ir.sequence,company_id:0 +#: field:ir.values,company_id:0 +#: view:res.company:0 +#: field:res.config.users,company_id:0 +#: field:res.currency,company_id:0 +#: field:res.partner,company_id:0 +#: field:res.partner.address,company_id:0 +#: view:res.users:0 +#: field:res.users,company_id:0 +msgid "Company" +msgstr "" + +#. module: base +#: view:res.users:0 +msgid "Email & Signature" +msgstr "" + +#. module: base +#: view:publisher_warranty.contract:0 +msgid "Publisher Warranty Contract" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Bulgarian / български език" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_aftersale +msgid "After-Sale Services" +msgstr "" + +#. module: base +#: view:ir.actions.todo:0 +msgid "Launch" +msgstr "" + +#. module: base +#: field:ir.actions.act_window,limit:0 +msgid "Limit" +msgstr "" + +#. module: base +#: help:ir.actions.server,wkf_model_id:0 +msgid "Workflow to be executed on this model." +msgstr "" + +#. module: base +#: model:res.country,name:base.jm +msgid "Jamaica" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,help:base.action_partner_category_form +msgid "" +"Manage the partner categories in order to better classify them for tracking " +"and analysis purposes. A partner may belong to several categories and " +"categories have a hierarchy structure: a partner belonging to a category " +"also belong to his parent category." +msgstr "" + +#. module: base +#: model:res.country,name:base.az +msgid "Azerbaijan" +msgstr "" + +#. module: base +#: code:addons/base/res/partner/partner.py:250 +#, python-format +msgid "Warning" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Arabic / الْعَرَبيّة" +msgstr "" + +#. module: base +#: model:res.country,name:base.vg +msgid "Virgin Islands (British)" +msgstr "" + +#. module: base +#: view:ir.property:0 +#: model:ir.ui.menu,name:base.next_id_15 +msgid "Parameters" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Czech / Čeština" +msgstr "" + +#. module: base +#: view:ir.actions.server:0 +msgid "Trigger Configuration" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,help:base.action_partner_supplier_form +msgid "" +"You can access all information regarding your suppliers from the supplier " +"form: accounting data, history of emails, meetings, purchases, etc. You can " +"uncheck the 'Suppliers' filter button in order to search in all your " +"partners, including customers and prospects." +msgstr "" + +#. module: base +#: model:res.country,name:base.rw +msgid "Rwanda" +msgstr "" + +#. module: base +#: view:ir.sequence:0 +msgid "Day of the week (0:Monday): %(weekday)s" +msgstr "" + +#. module: base +#: model:res.country,name:base.ck +msgid "Cook Islands" +msgstr "" + +#. module: base +#: field:ir.model.data,noupdate:0 +msgid "Non Updatable" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Klingon" +msgstr "" + +#. module: base +#: model:res.country,name:base.sg +msgid "Singapore" +msgstr "" + +#. module: base +#: selection:ir.actions.act_window,target:0 +msgid "Current Window" +msgstr "" + +#. module: base +#: view:ir.values:0 +msgid "Action Source" +msgstr "" + +#. module: base +#: view:res.config.view:0 +msgid "" +"If you use OpenERP for the first time we strongly advise you to select the " +"simplified interface, which has less features but is easier. You can always " +"switch later from the user preferences." +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_country +#: field:res.bank,country:0 +#: view:res.country:0 +#: field:res.country.state,country_id:0 +#: field:res.partner,country:0 +#: view:res.partner.address:0 +#: field:res.partner.address,country_id:0 +#: field:res.partner.bank,country_id:0 +msgid "Country" +msgstr "" + +#. module: base +#: field:ir.model.fields,complete_name:0 +#: field:ir.ui.menu,complete_name:0 +msgid "Complete Name" +msgstr "" + +#. module: base +#: field:ir.values,object:0 +msgid "Is Object" +msgstr "" + +#. module: base +#: view:ir.rule:0 +msgid "" +"1. Global rules are combined together with a logical AND operator, and with " +"the result of the following steps" +msgstr "" + +#. module: base +#: field:res.partner.category,name:0 +msgid "Category Name" +msgstr "" + +#. module: base +#: model:res.partner.category,name:base.res_partner_category_15 +msgid "IT sector" +msgstr "" + +#. module: base +#: view:ir.actions.act_window:0 +msgid "Select Groups" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "%X - Appropriate time representation." +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Spanish (SV) / Español (SV)" +msgstr "" + +#. module: base +#: help:res.lang,grouping:0 +msgid "" +"The Separator Format should be like [,n] where 0 < n :starting from Unit " +"digit.-1 will end the separation. e.g. [3,2,-1] will represent 106500 to be " +"1,06,500;[1,2,-1] will represent it to be 106,50,0;[3] will represent it as " +"106,500. Provided ',' as the thousand separator in each case." +msgstr "" + +#. module: base +#: view:res.company:0 +msgid "Portrait" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_model.py:317 +#, python-format +msgid "Can only rename one column at a time!" +msgstr "" + +#. module: base +#: selection:ir.translation,type:0 +msgid "Wizard Button" +msgstr "" + +#. module: base +#: selection:ir.translation,type:0 +msgid "Report/Template" +msgstr "" + +#. module: base +#: selection:ir.actions.act_window.view,view_mode:0 +#: selection:ir.ui.view,type:0 +#: selection:wizard.ir.model.menu.create.line,view_type:0 +msgid "Graph" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_actions_server +#: selection:ir.ui.menu,action:0 +msgid "ir.actions.server" +msgstr "" + +#. module: base +#: field:ir.actions.configuration.wizard,progress:0 +#: field:res.config,progress:0 +#: field:res.config.installer,progress:0 +#: field:res.config.users,progress:0 +#: field:res.config.view,progress:0 +msgid "Configuration Progress" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.act_ir_actions_todo_form +#: model:ir.ui.menu,name:base.menu_ir_actions_todo_form +#: model:ir.ui.menu,name:base.next_id_11 +msgid "Configuration Wizards" +msgstr "" + +#. module: base +#: field:res.lang,code:0 +msgid "Locale Code" +msgstr "" + +#. module: base +#: field:workflow.activity,split_mode:0 +msgid "Split Mode" +msgstr "" + +#. module: base +#: view:base.module.upgrade:0 +msgid "Note that this operation might take a few minutes." +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_localisation +msgid "Localisation" +msgstr "" + +#. module: base +#: view:ir.actions.server:0 +msgid "Action to Launch" +msgstr "" + +#. module: base +#: view:ir.cron:0 +msgid "Execution" +msgstr "" + +#. module: base +#: field:ir.actions.server,condition:0 +#: field:workflow.transition,condition:0 +msgid "Condition" +msgstr "" + +#. module: base +#: help:ir.values,model_id:0 +msgid "This field is not used, it only helps you to select a good model." +msgstr "" + +#. module: base +#: field:ir.ui.view,name:0 +msgid "View Name" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Italian / Italiano" +msgstr "" + +#. module: base +#: field:ir.actions.report.xml,attachment:0 +msgid "Save As Attachment Prefix" +msgstr "" + +#. module: base +#: view:ir.actions.server:0 +msgid "" +"Only one client action will be executed, last client action will be " +"considered in case of multiple client actions." +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "%j - Day of the year [001,366]." +msgstr "" + +#. module: base +#: field:ir.actions.server,mobile:0 +msgid "Mobile No" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_partner_by_category +#: model:ir.actions.act_window,name:base.action_partner_category_form +#: model:ir.model,name:base.model_res_partner_category +#: model:ir.ui.menu,name:base.menu_partner_category_form +#: view:res.partner.category:0 +msgid "Partner Categories" +msgstr "" + +#. module: base +#: view:base.module.upgrade:0 +msgid "System Update" +msgstr "" + +#. module: base +#: selection:ir.translation,type:0 +msgid "Wizard Field" +msgstr "" + +#. module: base +#: help:ir.sequence,prefix:0 +msgid "Prefix value of the record for the sequence" +msgstr "" + +#. module: base +#: model:res.country,name:base.sc +msgid "Seychelles" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_partner_bank +#: view:res.partner.bank:0 +msgid "Bank Accounts" +msgstr "" + +#. module: base +#: model:res.country,name:base.sl +msgid "Sierra Leone" +msgstr "" + +#. module: base +#: view:res.company:0 +#: view:res.partner:0 +msgid "General Information" +msgstr "" + +#. module: base +#: model:res.country,name:base.tc +msgid "Turks and Caicos Islands" +msgstr "" + +#. module: base +#: field:res.partner.bank,owner_name:0 +msgid "Account Owner" +msgstr "" + +#. module: base +#: code:addons/base/res/res_user.py:256 +#, python-format +msgid "Company Switch Warning" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_res_widget_wizard +msgid "Homepage Widgets Management" +msgstr "" + +#. module: base +#: field:workflow,osv:0 +#: field:workflow.instance,res_type:0 +msgid "Resource Object" +msgstr "" + +#. module: base +#: help:ir.sequence,number_increment:0 +msgid "The next number of the sequence will be incremented by this number" +msgstr "" + +#. module: base +#: field:ir.cron,function:0 +#: field:res.partner.address,function:0 +#: selection:workflow.activity,kind:0 +msgid "Function" +msgstr "" + +#. module: base +#: view:res.widget:0 +msgid "Search Widget" +msgstr "" + +#. module: base +#: selection:ir.actions.todo,restart:0 +msgid "Never" +msgstr "" + +#. module: base +#: selection:res.partner.address,type:0 +msgid "Delivery" +msgstr "" + +#. module: base +#: model:res.partner.title,name:base.res_partner_title_pvt_ltd +#: model:res.partner.title,shortcut:base.res_partner_title_pvt_ltd +msgid "Corp." +msgstr "" + +#. module: base +#: model:res.country,name:base.gw +msgid "Guinea Bissau" +msgstr "" + +#. module: base +#: view:workflow.instance:0 +msgid "Workflow Instances" +msgstr "" + +#. module: base +#: code:addons/base/res/partner/partner.py:261 +#, python-format +msgid "Partners: " +msgstr "" + +#. module: base +#: model:res.country,name:base.kp +msgid "North Korea" +msgstr "" + +#. module: base +#: selection:ir.actions.server,state:0 +msgid "Create Object" +msgstr "" + +#. module: base +#: view:ir.filters:0 +#: field:res.log,context:0 +msgid "Context" +msgstr "" + +#. module: base +#: field:res.bank,bic:0 +msgid "BIC/Swift code" +msgstr "" + +#. module: base +#: model:res.partner.category,name:base.res_partner_category_1 +msgid "Prospect" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Polish / Język polski" +msgstr "" + +#. module: base +#: field:ir.exports,name:0 +msgid "Export Name" +msgstr "" + +#. module: base +#: help:res.partner.address,type:0 +msgid "" +"Used to select automatically the right address according to the context in " +"sales and purchases documents." +msgstr "" + +#. module: base +#: model:res.country,name:base.lk +msgid "Sri Lanka" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Russian / русский язык" +msgstr "" diff --git a/openerp/addons/base/i18n/sl.po b/openerp/addons/base/i18n/sl.po index fc0c7518e38..22d06500f88 100644 --- a/openerp/addons/base/i18n/sl.po +++ b/openerp/addons/base/i18n/sl.po @@ -7,14 +7,14 @@ msgstr "" "Project-Id-Version: OpenERP Server 5.0.4\n" "Report-Msgid-Bugs-To: support@openerp.com\n" "POT-Creation-Date: 2011-01-11 11:14+0000\n" -"PO-Revision-Date: 2010-12-01 06:59+0000\n" -"Last-Translator: OpenERP Administrators \n" +"PO-Revision-Date: 2011-09-26 18:06+0000\n" +"Last-Translator: Simon Vidmar \n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-09-01 04:43+0000\n" -"X-Generator: Launchpad (build 13827)\n" +"X-Launchpad-Export-Date: 2011-09-27 04:47+0000\n" +"X-Generator: Launchpad (build 14028)\n" #. module: base #: view:ir.filters:0 @@ -33,12 +33,12 @@ msgstr "Sveta Helena" #. module: base #: view:ir.actions.report.xml:0 msgid "Other Configuration" -msgstr "" +msgstr "Ostale nastavitve" #. module: base #: selection:ir.property,type:0 msgid "DateTime" -msgstr "" +msgstr "DatumČas" #. module: base #: code:addons/fields.py:534 @@ -47,12 +47,14 @@ msgid "" "The second argument of the many2many field %s must be a SQL table !You used " "%s, which is not a valid SQL table name." msgstr "" +"Drugi argument od polja many2many %s mora biti SQL tabela! Uporabili ste %s, " +"ki ni veljavno ime SQL tabele." #. module: base #: view:ir.values:0 #: field:ir.values,meta_unpickle:0 msgid "Metadata" -msgstr "Metapodatki" +msgstr "Meta podatki" #. module: base #: field:ir.ui.view,arch:0 @@ -73,7 +75,7 @@ msgstr "Oznaka (n.pr.: sl_SI)" #: field:workflow.transition,wkf_id:0 #: field:workflow.workitem,wkf_id:0 msgid "Workflow" -msgstr "Potek dela" +msgstr "Delovni proces" #. module: base #: view:partner.sms.send:0 @@ -98,12 +100,12 @@ msgstr "Špansko" #. module: base #: field:ir.actions.server,wkf_model_id:0 msgid "Workflow On" -msgstr "Vklopi potek dela" +msgstr "Vklopi delovni proces" #. module: base #: field:ir.actions.act_window,display_menu_tip:0 msgid "Display Menu Tips" -msgstr "Prikaži tip menija" +msgstr "Prikaži namige menija" #. module: base #: view:ir.module.module:0 @@ -117,6 +119,8 @@ msgid "" "You can not write in this document (%s) ! Be sure your user belongs to one " "of these groups: %s." msgstr "" +"Ne morete pisati v ta dokument (%s)! Bodite prepričani, da vaš uporabnik " +"sodi v eno od teh skupin: %s." #. module: base #: help:ir.model.fields,domain:0 @@ -125,11 +129,14 @@ msgid "" "specified as a Python expression defining a list of triplets. For example: " "[('color','=','red')]" msgstr "" +"Opcijska domena, ki omeji možne vrednosti za sorodna polja, navedena kot " +"Python izrazi, ki opredeljujejo seznam trojčkov. Kot npr: " +"[('color','=','red')]" #. module: base #: field:res.partner,ref:0 msgid "Reference" -msgstr "Referenca" +msgstr "Sklic" #. module: base #: field:ir.actions.act_window,target:0 @@ -140,7 +147,7 @@ msgstr "Ciljno okno" #: code:addons/base/res/res_user.py:507 #, python-format msgid "Warning!" -msgstr "" +msgstr "Opozorilo!" #. module: base #: code:addons/base/ir/ir_model.py:304 @@ -149,12 +156,14 @@ msgid "" "Properties of base fields cannot be altered in this manner! Please modify " "them through Python code, preferably through a custom addon!" msgstr "" +"Lastnosti baze polj ni mogoče spremeniti na ta način! Prosimo, da jih " +"spremenite preko kode Python, po možnosti z dodatkom po meri!" #. module: base #: code:addons/osv.py:133 #, python-format msgid "Constraint Error" -msgstr "" +msgstr "Napaka omejitve" #. module: base #: model:ir.model,name:base.model_ir_ui_view_custom @@ -164,14 +173,14 @@ msgstr "ir.ui.view.custom" #. module: base #: model:res.country,name:base.sz msgid "Swaziland" -msgstr "Svazi" +msgstr "Švica" #. module: base #: code:addons/orm.py:1993 #: code:addons/orm.py:3653 #, python-format msgid "created." -msgstr "" +msgstr "ustvarjeno." #. module: base #: model:res.partner.category,name:base.res_partner_category_woodsuppliers0 @@ -185,17 +194,19 @@ msgid "" "Some installed modules depend on the module you plan to Uninstall :\n" " %s" msgstr "" +"Nekateri nameščeni moduli so odvisni od modula, ki ga želite odstraniti:\n" +" %s" #. module: base #: field:ir.sequence,number_increment:0 msgid "Increment Number" -msgstr "Prirastek zaporedja" +msgstr "Dobiček" #. module: base #: model:ir.actions.act_window,name:base.action_res_company_tree #: model:ir.ui.menu,name:base.menu_action_res_company_tree msgid "Company's Structure" -msgstr "Struktura družbe" +msgstr "Struktura podjetja" #. module: base #: selection:base.language.install,lang:0 @@ -205,13 +216,15 @@ msgstr "" #. module: base #: view:res.partner:0 msgid "Search Partner" -msgstr "" +msgstr "Iskanje partnerja" #. module: base #: code:addons/base/res/res_user.py:132 #, python-format msgid "\"smtp_server\" needs to be set to send mails to users" msgstr "" +"\"smtp strežnik\" mora biti nastavljen, da se lahko pošilja e-pošto " +"uporabnikom" #. module: base #: code:addons/base/module/wizard/base_export_language.py:60 @@ -232,7 +245,7 @@ msgstr "Število modulov" #. module: base #: help:multi_company.default,company_dest_id:0 msgid "Company to store the current record" -msgstr "" +msgstr "Podjetje za shranjevanje trenutnega zapisa" #. module: base #: field:res.partner.bank.type.field,size:0 @@ -242,7 +255,7 @@ msgstr "Maksimalna velikost" #. module: base #: field:res.partner.address,name:0 msgid "Contact Name" -msgstr "Naziv stika" +msgstr "Ime stika" #. module: base #: code:addons/base/module/wizard/base_export_language.py:56 @@ -252,12 +265,12 @@ msgid "" "text editor. The file encoding is UTF-8." msgstr "" "Shrani ta dokument v datoteko %s in ga uredi z ustreznim urejevalnikom. " -"Kodni tabela je UTF-8." +"Kodni nabor je UTF-8." #. module: base #: sql_constraint:res.lang:0 msgid "The name of the language must be unique !" -msgstr "" +msgstr "Ime jezika mora biti edinstven!" #. module: base #: selection:res.request,state:0 @@ -273,12 +286,12 @@ msgstr "Ime čarovnika" #: code:addons/orm.py:2160 #, python-format msgid "Invalid group_by" -msgstr "" +msgstr "Neveljavna skupina_z" #. module: base #: field:res.partner,credit_limit:0 msgid "Credit Limit" -msgstr "" +msgstr "Meja posojila" #. module: base #: field:ir.model.data,date_update:0 @@ -288,12 +301,12 @@ msgstr "Datum posodobitve" #. module: base #: view:ir.attachment:0 msgid "Owner" -msgstr "" +msgstr "Lastnik" #. module: base #: field:ir.actions.act_window,src_model:0 msgid "Source Object" -msgstr "Izvorni objekt" +msgstr "Izvorni predmet" #. module: base #: view:ir.actions.todo:0 @@ -309,7 +322,7 @@ msgstr "ir.ui.view_sc" #: field:res.widget.user,widget_id:0 #: field:res.widget.wizard,widgets_list:0 msgid "Widget" -msgstr "" +msgstr "Gradnik" #. module: base #: view:ir.model.access:0 @@ -323,23 +336,23 @@ msgstr "Skupina" #: field:ir.translation,name:0 #: field:res.partner.bank.type.field,name:0 msgid "Field Name" -msgstr "Naziv polja" +msgstr "Ime polja" #. module: base #: wizard_view:server.action.create,init:0 #: wizard_field:server.action.create,init,type:0 msgid "Select Action Type" -msgstr "" +msgstr "Izberi tip dejanja" #. module: base #: model:res.country,name:base.tv msgid "Tuvalu" -msgstr "tuvalujščina" +msgstr "Tuvalu" #. module: base #: selection:ir.model,state:0 msgid "Custom Object" -msgstr "Objekt po meri" +msgstr "Predmet po meri" #. module: base #: field:res.lang,date_format:0 @@ -375,7 +388,7 @@ msgstr "Francoska Gvajana" #. module: base #: selection:base.language.install,lang:0 msgid "Greek / Ελληνικά" -msgstr "" +msgstr "Grški / Ελληνικά" #. module: base #: selection:base.language.install,lang:0 @@ -388,22 +401,24 @@ msgid "" "If you check this, then the second time the user prints with same attachment " "name, it returns the previous report." msgstr "" +"Če označite to, potem bo drugič ko uporabnik natisne z enakim imenom " +"prilogo, se vrne v prejšnje poročilo." #. module: base #: code:addons/orm.py:904 #, python-format msgid "The read method is not implemented on this object !" -msgstr "Metoda 'read' ni implementirana za ta objekt." +msgstr "Metoa 'read' ni implementirana za ta predmet." #. module: base #: help:res.lang,iso_code:0 msgid "This ISO code is the name of po files to use for translations" -msgstr "" +msgstr "ISO koda je ime po datotek za uporabo prevodov." #. module: base #: view:base.module.upgrade:0 msgid "Your system will be updated." -msgstr "" +msgstr "Vaš sistem bo posodobljen." #. module: base #: field:ir.actions.todo,note:0 @@ -414,7 +429,7 @@ msgstr "Besedilo" #. module: base #: field:res.country,name:0 msgid "Country Name" -msgstr "Naziv države" +msgstr "Ime države" #. module: base #: model:res.country,name:base.co @@ -430,7 +445,7 @@ msgstr "Razporedi nadgradnjo" #: code:addons/orm.py:838 #, python-format msgid "Key/value '%s' not found in selection field '%s'" -msgstr "" +msgstr "Ključ/vrednost '%s' ni mogoče najti v izbranem polju '%s'" #. module: base #: help:res.country,code:0 @@ -449,18 +464,18 @@ msgstr "Palau" #. module: base #: view:res.partner:0 msgid "Sales & Purchases" -msgstr "Prodaja in nabava" +msgstr "Prodaja & Nabava" #. module: base #: view:ir.translation:0 msgid "Untranslated" -msgstr "" +msgstr "Ni prevedeno" #. module: base #: help:ir.actions.act_window,context:0 msgid "" "Context dictionary as Python expression, empty by default (Default: {})" -msgstr "" +msgstr "Kontekst slovar kot izraz Python, prazno privzeto (privzeto: {})" #. module: base #: model:ir.actions.act_window,name:base.ir_action_wizard @@ -472,7 +487,7 @@ msgstr "Čarovniki" #. module: base #: model:res.partner.category,name:base.res_partner_category_miscellaneoussuppliers0 msgid "Miscellaneous Suppliers" -msgstr "" +msgstr "Razni dobavitelji" #. module: base #: code:addons/base/ir/ir_model.py:255 @@ -483,12 +498,12 @@ msgstr "Nazivi polj po meri se morajo začeti z 'x_'." #. module: base #: help:ir.actions.server,action_id:0 msgid "Select the Action Window, Report, Wizard to be executed." -msgstr "" +msgstr "Izberite okno dejanja, poročila, čarovnika, ki naj bo izvršeno." #. module: base #: view:res.config.users:0 msgid "New User" -msgstr "" +msgstr "Nov uporabnik" #. module: base #: view:base.language.export:0 @@ -504,7 +519,7 @@ msgstr "Opis modela" #: help:ir.actions.act_window,src_model:0 msgid "" "Optional model name of the objects on which this action should be visible" -msgstr "" +msgstr "Ime opcijskega modula predmeta na katerem bo to dejanje vidno" #. module: base #: field:workflow.transition,trigger_expr_id:0 @@ -519,7 +534,7 @@ msgstr "Jordanija" #. module: base #: view:ir.module.module:0 msgid "Certified" -msgstr "" +msgstr "Preverjeno" #. module: base #: model:res.country,name:base.er @@ -530,12 +545,12 @@ msgstr "Eritreja" #: view:res.config:0 #: view:res.config.installer:0 msgid "description" -msgstr "" +msgstr "opis" #. module: base #: model:ir.ui.menu,name:base.menu_base_action_rule msgid "Automated Actions" -msgstr "" +msgstr "Avtomatska dejanja" #. module: base #: model:ir.model,name:base.model_ir_actions_actions @@ -545,7 +560,7 @@ msgstr "ir.actions.actions" #. module: base #: view:partner.wizard.ean.check:0 msgid "Want to check Ean ? " -msgstr "" +msgstr "Ali želite preveriti Ean? " #. module: base #: field:ir.values,key2:0 @@ -559,16 +574,19 @@ msgid "" "Launchpad.net, our open source project management facility. We use their " "online interface to synchronize all translations efforts." msgstr "" +"OpenERP prevodi (jedro, moduli, klienti) se upravljajp skoz Launchpad.net, " +"ki je naš odprto kodni objekt za upravljanje. Uporabljamo njihov spletni " +"vmesnik za sinhronizacijo vseh prevodov." #. module: base #: field:res.partner,title:0 msgid "Partner Form" -msgstr "" +msgstr "Obrazec partnerja" #. module: base #: selection:base.language.install,lang:0 msgid "Swedish / svenska" -msgstr "Švedsko" +msgstr "Švedsko / svenska" #. module: base #: model:res.country,name:base.rs @@ -596,27 +614,27 @@ msgstr "Zaporedja" #. module: base #: model:ir.model,name:base.model_base_language_import msgid "Language Import" -msgstr "" +msgstr "Uvoz jezika" #. module: base #: model:ir.model,name:base.model_res_config_users msgid "res.config.users" -msgstr "" +msgstr "Copy text \t res.config.users" #. module: base #: selection:base.language.install,lang:0 msgid "Albanian / Shqip" -msgstr "" +msgstr "Albansko /Shqip" #. module: base #: model:ir.ui.menu,name:base.menu_crm_config_opportunity msgid "Opportunities" -msgstr "" +msgstr "Priložnosti" #. module: base #: model:ir.model,name:base.model_base_language_export msgid "base.language.export" -msgstr "" +msgstr "base.language.export" #. module: base #: model:res.country,name:base.pg @@ -627,6 +645,7 @@ msgstr "Papua Nova Gvineja" #: help:ir.actions.report.xml,report_type:0 msgid "Report Type, e.g. pdf, html, raw, sxw, odt, html2html, mako2html, ..." msgstr "" +"Tip poročila, npr. pdf, html, raw, sxw, odt, html2html, mako2html, ..." #. module: base #: model:res.partner.category,name:base.res_partner_category_4 @@ -641,12 +660,12 @@ msgstr "," #. module: base #: view:res.partner:0 msgid "My Partners" -msgstr "" +msgstr "Moji partnerji" #. module: base #: view:ir.actions.report.xml:0 msgid "XML Report" -msgstr "" +msgstr "XML poročilo" #. module: base #: model:res.country,name:base.es @@ -662,13 +681,13 @@ msgstr "Uvoz / Izvoz" #: help:ir.actions.act_window,domain:0 msgid "" "Optional domain filtering of the destination data, as a Python expression" -msgstr "" +msgstr "Dodatna domena filtriranje za destinacije podatkov, kot izraz Python" #. module: base #: model:ir.actions.act_window,name:base.action_view_base_module_upgrade #: model:ir.model,name:base.model_base_module_upgrade msgid "Module Upgrade" -msgstr "" +msgstr "Posodobitev modula" #. module: base #: view:res.config.users:0 @@ -676,11 +695,13 @@ msgid "" "Groups are used to define access rights on objects and the visibility of " "screens and menus" msgstr "" +"Skupine se uporablja za opredelitev pravice dostopa do predmetov, ter za " +"vidnost zaslonov in menijev" #. module: base #: selection:base.language.install,lang:0 msgid "Spanish (UY) / Español (UY)" -msgstr "" +msgstr "Špansko (UY) / Español (UY)" #. module: base #: field:res.partner,mobile:0 @@ -697,7 +718,7 @@ msgstr "Oman" #: model:ir.actions.act_window,name:base.action_payterm_form #: model:ir.model,name:base.model_res_payterm msgid "Payment term" -msgstr "Plačilni pogoj" +msgstr "" #. module: base #: model:res.country,name:base.nu @@ -712,7 +733,7 @@ msgstr "Delovni dnevi" #. module: base #: selection:ir.module.module,license:0 msgid "Other OSI Approved Licence" -msgstr "" +msgstr "Ostale OSI dvoljene licence" #. module: base #: help:res.config.users,context_lang:0 @@ -721,12 +742,13 @@ msgid "" "Sets the language for the user's user interface, when UI translations are " "available" msgstr "" +"Nastavi jezik za uporabniški vmesnik uporabnika, ko so prevodi UI na voljo" #. module: base #: code:addons/orm.py:1043 #, python-format msgid "The unlink method is not implemented on this object !" -msgstr "Metoda 'unlink' ni implementirana za ta objekt." +msgstr "Metoda 'unlink' ni implementirana za ta predmet." #. module: base #: model:ir.actions.act_window,name:base.act_menu_create @@ -743,12 +765,12 @@ msgstr "Indija" #: model:ir.actions.act_window,name:base.res_request_link-act #: model:ir.ui.menu,name:base.menu_res_request_link_act msgid "Request Reference Types" -msgstr "" +msgstr "Zahtevaj tipe sklicov" #. module: base #: view:ir.values:0 msgid "client_action_multi, client_action_relate" -msgstr "" +msgstr "client_action_multi, client_action_relate" #. module: base #: model:res.country,name:base.ad @@ -759,12 +781,12 @@ msgstr "Andora, Principat" #: field:ir.module.category,child_ids:0 #: field:res.partner.category,child_ids:0 msgid "Child Categories" -msgstr "Kategorije otrok" +msgstr "Kategorije podrejenih" #. module: base #: model:ir.model,name:base.model_ir_config_parameter msgid "ir.config_parameter" -msgstr "" +msgstr "ir.config_parameter" #. module: base #: selection:base.language.export,format:0 @@ -799,6 +821,8 @@ msgid "" "Language with code \"%s\" is not defined in your system !\n" "Define it through the Administration menu." msgstr "" +"Jezik s kodo \"%s\" ni določen na vašem sistemu!\n" +"Določite ga v Administracijskem meniju." #. module: base #: model:res.country,name:base.gu @@ -808,13 +832,13 @@ msgstr "Guam (USA)" #. module: base #: model:ir.ui.menu,name:base.menu_hr_project msgid "Human Resources Dashboard" -msgstr "" +msgstr "Nadzorna plošča človeških virov" #. module: base #: code:addons/base/res/res_user.py:507 #, python-format msgid "Setting empty passwords is not allowed for security reasons!" -msgstr "" +msgstr "Nastavitev brez gesla ni dovoljeno zaradi varnostnih razlogov!" #. module: base #: selection:ir.actions.server,state:0 @@ -825,7 +849,7 @@ msgstr "Začasno" #. module: base #: constraint:ir.ui.view:0 msgid "Invalid XML for View Architecture!" -msgstr "Neveljaven XML za arhitekturo pogleda." +msgstr "Neveljaven XML za arhitekturo pogleda!" #. module: base #: model:res.country,name:base.ky @@ -848,28 +872,28 @@ msgstr "Prehodi" #: code:addons/orm.py:4020 #, python-format msgid "Record #%d of %s not found, cannot copy!" -msgstr "" +msgstr "Zapisa #%d od %s ni mogoče najti. Ne morem kopirati!" #. module: base #: field:ir.module.module,contributors:0 msgid "Contributors" -msgstr "" +msgstr "Sodelavci" #. module: base #: selection:ir.property,type:0 msgid "Char" -msgstr "" +msgstr "Znak" #. module: base #: model:ir.actions.act_window,name:base.action_publisher_warranty_contract_form #: model:ir.ui.menu,name:base.menu_publisher_warranty_contract msgid "Contracts" -msgstr "" +msgstr "Pogodbe" #. module: base #: selection:base.language.install,lang:0 msgid "Spanish (AR) / Español (AR)" -msgstr "Špansko" +msgstr "Špansko (AR) / Español (AR)" #. module: base #: model:res.country,name:base.ug @@ -879,17 +903,17 @@ msgstr "Uganda" #. module: base #: field:ir.model.access,perm_unlink:0 msgid "Delete Access" -msgstr "" +msgstr "Izbriši dostop" #. module: base #: model:res.country,name:base.ne msgid "Niger" -msgstr "Niger" +msgstr "Nigerija" #. module: base #: selection:base.language.install,lang:0 msgid "Chinese (HK)" -msgstr "" +msgstr "Kitajsko (HK)" #. module: base #: model:res.country,name:base.ba @@ -903,11 +927,14 @@ msgid "" "Lauchpad's web interface (Rosetta). If you need to perform mass translation, " "Launchpad also allows uploading full .po files at once" msgstr "" +"Če želite izboljšati ali razširiti uradne prevode, morate uporabljati " +"neposredno Lauchpad spletni vmesnik (Rosetta). Če morate opraviti množično " +"prevod, Launchpad tudi omogoča tudi nalaganje polno. PO datotek hkrati" #. module: base #: selection:base.language.install,lang:0 msgid "Spanish (GT) / Español (GT)" -msgstr "" +msgstr "Špansko (GT) / Español (GT)" #. module: base #: view:res.lang:0 @@ -916,12 +943,15 @@ msgid "" "decimal number [00,53]. All days in a new year preceding the first Monday " "are considered to be in week 0." msgstr "" +"%W - Številka tedna v letu (ponedeljek kot prvi dan v tednu), kot decimalno " +"število [00,53]. Vse dni v novem letu pred prvim ponedeljekom se šteje, da " +"je v tednu 0." #. module: base #: field:ir.module.module,website:0 #: field:res.partner,website:0 msgid "Website" -msgstr "Spletno mesto" +msgstr "Spletna stran" #. module: base #: model:res.country,name:base.gs @@ -931,7 +961,7 @@ msgstr "" #. module: base #: field:ir.actions.url,url:0 msgid "Action URL" -msgstr "" +msgstr "URL dejanja" #. module: base #: field:base.module.import,module_name:0 @@ -941,13 +971,13 @@ msgstr "Ime modula" #. module: base #: model:res.country,name:base.mh msgid "Marshall Islands" -msgstr "Marshallovi otoki" +msgstr "Maršalovi otoki" #. module: base #: code:addons/base/ir/ir_model.py:328 #, python-format msgid "Changing the model of a field is forbidden!" -msgstr "" +msgstr "Spreminjanje modela polja ni dovoljeno!" #. module: base #: model:res.country,name:base.ht @@ -958,7 +988,7 @@ msgstr "Haiti" #: view:ir.ui.view:0 #: selection:ir.ui.view,type:0 msgid "Search" -msgstr "" +msgstr "Iskanje" #. module: base #: code:addons/osv.py:136 @@ -969,38 +999,43 @@ msgid "" "reference it\n" "- creation/update: a mandatory field is not correctly set" msgstr "" +"Operacije ni mogoče zaključiti zaradi naslednjih zadev:\n" +"- izbris: poizkušate izbrisati zapis med tem, ko drug zapis še vedno kaže " +"nanj\n" +"- ustvariti/posodobiti: obvezno polje ni pravilno nastavljeno" #. module: base #: view:ir.rule:0 msgid "" "2. Group-specific rules are combined together with a logical AND operator" msgstr "" +"Skupinsko-specifična pravila so združena skupaj z logičnim operatorjem AND" #. module: base #: code:addons/base/res/res_user.py:206 #, python-format msgid "Operation Canceled" -msgstr "" +msgstr "Operacija preklicana" #. module: base #: help:base.language.export,lang:0 msgid "To export a new language, do not select a language." -msgstr "Jezika ne izbirajte za izvoz novega jezika." +msgstr "Ne izbirajte jezika za izvoz novega jezika." #. module: base #: view:res.request:0 msgid "Request Date" -msgstr "" +msgstr "Datum zahtevka" #. module: base #: model:ir.ui.menu,name:base.menu_hr_dasboard msgid "Dashboard" -msgstr "" +msgstr "Nadzorna plošča" #. module: base #: model:ir.ui.menu,name:base.menu_purchase_root msgid "Purchases" -msgstr "" +msgstr "Nabave" #. module: base #: model:res.country,name:base.md @@ -1034,13 +1069,13 @@ msgstr "ir.exports" #: code:addons/base/module/wizard/base_update_translations.py:38 #, python-format msgid "No language with code \"%s\" exists" -msgstr "" +msgstr "Ne obstaja jezik s kodo \"%s\"" #. module: base #: code:addons/base/publisher_warranty/publisher_warranty.py:163 #, python-format msgid "Error during communication with the publisher warranty server." -msgstr "" +msgstr "Napaka pri komuniciranju s strežnikom založniške garancije." #. module: base #: help:ir.actions.server,email:0 @@ -1049,11 +1084,14 @@ msgid "" "you select the invoice, then `object.invoice_address_id.email` is the field " "which gives the correct address" msgstr "" +"Zagotavlja polja, ki se bodo uporabljala za pridobivanje e-poštnih naslovov, " +"npr. ko izberete račun, nato pa polje `object.invoice_address_id.email`, ki " +"daje pravi naslov" #. module: base #: view:res.lang:0 msgid "%Y - Year with century." -msgstr "" +msgstr "%Y - leto s stoletji" #. module: base #: report:ir.module.reference.graph:0 @@ -1067,22 +1105,25 @@ msgid "" "system. After the contract has been registered, you will be able to send " "issues directly to OpenERP." msgstr "" +"Ta čarovnik vam pomaga registrirati pogodbo garancije založnika v vašem " +"OpenERP sistemu. Ko je pogodba registrirana, boste lahko poslali vprašanja " +"direktno na OpenERP." #. module: base #: code:addons/orm.py:1744 #, python-format msgid "The search method is not implemented on this object !" -msgstr "Metoda 'search' ni implementirana za ta objekt." +msgstr "Metoda 'search' ni implementira v predmet." #. module: base #: view:wizard.ir.model.menu.create:0 msgid "Create _Menu" -msgstr "" +msgstr "Ustvari_meni" #. module: base #: field:res.payterm,name:0 msgid "Payment Term (short name)" -msgstr "" +msgstr "Plačilni pogoj (kratko ime)" #. module: base #: model:ir.model,name:base.model_res_bank @@ -1102,11 +1143,13 @@ msgid "" "If you check this box, your customized translations will be overwritten and " "replaced by the official ones." msgstr "" +"Če označite to polje, bodo prilagojeni prevodi prepisani in zamenjani z " +"uradnimi." #. module: base #: field:ir.actions.report.xml,report_rml:0 msgid "Main report file path" -msgstr "" +msgstr "Pot datoteke glavnega poročila" #. module: base #: model:ir.actions.act_window,name:base.ir_action_report_xml @@ -1122,6 +1165,8 @@ msgid "" "If set to true, the action will not be displayed on the right toolbar of a " "form view." msgstr "" +"Če je nastavljeno na true, potem to dejanje ne bo prikazano v desni orodni " +"vrstici pogleda obrazca." #. module: base #: field:workflow,on_create:0 @@ -1135,6 +1180,8 @@ msgid "" "'%s' contains too many dots. XML ids should not contain dots ! These are " "used to refer to other modules data, as in module.reference_id" msgstr "" +"'%s' vsebuje preveč pik. XML id-ki ne smejo vsebovati pik! To se uporablja " +"za nanašanje na druge podatke modulov, kot je module.reference_id" #. module: base #: field:partner.sms.send,user:0 @@ -1149,6 +1196,8 @@ msgid "" "Access all the fields related to the current object using expressions, i.e. " "object.partner_id.name " msgstr "" +"Dostop do vseh polj, povezanih s trenutnim predmetom s pomočjo izrazov, npr. " +"object.partner_id.name " #. module: base #: model:ir.model,name:base.model_res_country_state @@ -1158,7 +1207,7 @@ msgstr "Zvezna država" #. module: base #: selection:ir.property,type:0 msgid "Float" -msgstr "" +msgstr "Plavajoče" #. module: base #: model:ir.model,name:base.model_res_request_link @@ -1168,14 +1217,14 @@ msgstr "res.request.link" #. module: base #: field:ir.actions.wizard,name:0 msgid "Wizard Info" -msgstr "" +msgstr "Info čarovnika" #. module: base #: view:base.language.export:0 #: model:ir.actions.act_window,name:base.action_wizard_lang_export #: model:ir.ui.menu,name:base.menu_wizard_lang_export msgid "Export Translation" -msgstr "" +msgstr "Izvoz prevoda" #. module: base #: help:res.log,secondary:0 @@ -1183,6 +1232,7 @@ msgid "" "Do not display this log if it belongs to the same object the user is working " "on" msgstr "" +"Ne prikaži dnevnika, če pripada na istem predmetu na katerem dela uporabnik" #. module: base #: model:res.country,name:base.tp @@ -1206,6 +1256,19 @@ msgid "" "%(user_signature)s\n" "%(company_name)s" msgstr "" +"Datum: %(date)s\n" +"\n" +"Spoštovani %(partner_name)s,\n" +"\n" +"Prosimo, najdete v priponki opomnik vseh vaših neplačanih računov, skupni " +"znesek:\n" +"\n" +"%(followup_amount).2f %(company_currency)s\n" +"\n" +"Hvala,\n" +"--\n" +"%(user_signature)s\n" +"%(company_name)s" #. module: base #: field:res.currency,accuracy:0 @@ -1225,7 +1288,7 @@ msgstr "wizard.ir.model.menu.create.line" #. module: base #: field:ir.attachment,res_id:0 msgid "Attached ID" -msgstr "" +msgstr "ID pripetja" #. module: base #: view:ir.sequence:0 @@ -1240,7 +1303,7 @@ msgstr "Maldivi" #. module: base #: help:ir.values,res_id:0 msgid "Keep 0 if the action must appear on all resources." -msgstr "" +msgstr "Obdržite 0, če se mora dejanje pojaviti v vseh virih." #. module: base #: model:ir.model,name:base.model_ir_rule @@ -1258,13 +1321,15 @@ msgid "" "Condition that is to be tested before action is executed, e.g. " "object.list_price > object.cost_price" msgstr "" +"Pogoj, ki ga je treba preskusiti, preden se dejanje izvede, npr. " +"object.list_price > object.cost_price" #. module: base #: code:addons/base/res/partner/partner.py:155 #: code:addons/base/res/res_company.py:66 #, python-format msgid " (copy)" -msgstr "" +msgstr " (kopija)" #. module: base #: view:res.lang:0 @@ -1281,13 +1346,13 @@ msgstr "Partnerji" #. module: base #: field:res.partner.category,parent_left:0 msgid "Left parent" -msgstr "" +msgstr "Levi izvor" #. module: base #: model:ir.actions.act_window,name:base.res_widget_act_window #: model:ir.ui.menu,name:base.menu_res_widget_act_window msgid "Homepage Widgets" -msgstr "" +msgstr "Gradnik domače strani" #. module: base #: help:ir.actions.server,message:0 @@ -1295,16 +1360,18 @@ msgid "" "Specify the message. You can use the fields from the object. e.g. `Dear [[ " "object.partner_id.name ]]`" msgstr "" +"Navedite sporočilo. Lahko uporabite polja iz predmeta. npr. 'Spoštovani " +"[[object.partner_id.name]]'" #. module: base #: field:ir.attachment,res_model:0 msgid "Attached Model" -msgstr "" +msgstr "Pripeti model" #. module: base #: view:ir.rule:0 msgid "Domain Setup" -msgstr "" +msgstr "Namestitev domene" #. module: base #: field:ir.actions.server,trigger_name:0 @@ -1342,7 +1409,7 @@ msgstr "Formula" #: code:addons/base/res/res_user.py:389 #, python-format msgid "Can not remove root user!" -msgstr "Ne morete odstaniti uporabnika 'root'." +msgstr "Ne morete odstaniti uporabnika 'root'!" #. module: base #: model:res.country,name:base.mw @@ -1354,7 +1421,7 @@ msgstr "Malavi" #: code:addons/base/res/res_user.py:413 #, python-format msgid "%s (copy)" -msgstr "" +msgstr "%s (kopija)" #. module: base #: field:res.partner.address,type:0 @@ -1364,7 +1431,7 @@ msgstr "Vrsta naslova" #. module: base #: view:ir.ui.menu:0 msgid "Full Path" -msgstr "" +msgstr "Celotna pot" #. module: base #: view:res.request:0 @@ -1378,11 +1445,14 @@ msgid "" "decimal number [00,53]. All days in a new year preceding the first Sunday " "are considered to be in week 0." msgstr "" +"%U - številka tedna v letu (nedelja kot prvi dan tedna) je decimalno " +"število[00,53]. Vse dnevi v novem letu pred prvo nedeljo se šteje, da je v 0 " +"tednu." #. module: base #: view:ir.ui.view:0 msgid "Advanced" -msgstr "" +msgstr "Napredno" #. module: base #: model:res.country,name:base.fi @@ -1396,23 +1466,23 @@ msgstr "Finska" #: selection:ir.ui.view,type:0 #: selection:wizard.ir.model.menu.create.line,view_type:0 msgid "Tree" -msgstr "Drevo" +msgstr "Drevesni prikaz" #. module: base #: help:res.config.users,password:0 msgid "" "Keep empty if you don't want the user to be able to connect on the system." -msgstr "" +msgstr "Obdržite prazno, če ne želite, da se uporabnik poveže na sistem." #. module: base #: view:ir.actions.server:0 msgid "Create / Write / Copy" -msgstr "" +msgstr "Ustvari / Zapiši / Kopiraj" #. module: base #: view:base.language.export:0 msgid "https://help.launchpad.net/Translations" -msgstr "" +msgstr "https://help.launchpad.net/Translations" #. module: base #: field:ir.actions.act_window,view_mode:0 @@ -1425,27 +1495,29 @@ msgid "" "When using CSV format, please also check that the first line of your file is " "one of the following:" msgstr "" +"Ko uporabljate CSV format, prosim preverite tudi prve vrstice vaše datoteke " +"ena od naslednje:" #. module: base #: code:addons/fields.py:114 #, python-format msgid "Not implemented search_memory method !" -msgstr "Metoda 'search_memory' ni implementirana." +msgstr "Metoda 'search_memory' ni implementirana!" #. module: base #: view:res.log:0 msgid "Logs" -msgstr "" +msgstr "Dnevniki" #. module: base #: selection:base.language.install,lang:0 msgid "Spanish / Español" -msgstr "Špansko" +msgstr "Špansko / Español" #. module: base #: selection:base.language.install,lang:0 msgid "Korean (KP) / 한국어 (KP)" -msgstr "" +msgstr "Korejsko (KP) / 한국어 (KP)" #. module: base #: view:base.module.update:0 @@ -1453,6 +1525,8 @@ msgid "" "This wizard will scan all module repositories on the server side to detect " "newly added modules as well as any change to existing modules." msgstr "" +"Ta čarovnik po pregledal vse skladišča modulov na strani strežnik za " +"odkrivanje novo dodanih modulov kot tudi vse spremembe na obstoječih modulih." #. module: base #: field:res.company,logo:0 @@ -1462,7 +1536,7 @@ msgstr "Logotip" #. module: base #: view:res.partner.address:0 msgid "Search Contact" -msgstr "" +msgstr "Išči po stikih" #. module: base #: view:ir.module.module:0 @@ -1486,13 +1560,13 @@ msgstr "Bahami" msgid "" "Couldn't generate the next id because some partners have an alphabetic id !" msgstr "" -"Ni bilo možno ustvariti naslednjega IDja, saj imajo nekateri partnerji " -"črkovni ID." +"Ni bilo možno ustvariti sledečega IDja, ker imajo nekateri partnerji črkovni " +"ID!" #. module: base #: view:ir.attachment:0 msgid "Attachment" -msgstr "Priponke" +msgstr "Priponka" #. module: base #: model:res.country,name:base.ie @@ -1508,12 +1582,12 @@ msgstr "Število osveženih modulov" #: code:addons/fields.py:100 #, python-format msgid "Not implemented set_memory method !" -msgstr "Metoda 'set_memory' ni implementirana." +msgstr "Metoda 'set_memory' ni implementirana!" #. module: base #: view:workflow.activity:0 msgid "Workflow Activity" -msgstr "" +msgstr "Aktivnost delovnega procesa" #. module: base #: view:ir.rule:0 @@ -1521,6 +1595,8 @@ msgid "" "Example: GLOBAL_RULE_1 AND GLOBAL_RULE_2 AND ( (GROUP_A_RULE_1 AND " "GROUP_A_RULE_2) OR (GROUP_B_RULE_1 AND GROUP_B_RULE_2) )" msgstr "" +"Primer: GLOBAL_RULE_1 AND GLOBAL_RULE_2 AND ( (GROUP_A_RULE_1 AND " +"GROUP_A_RULE_2) OR (GROUP_B_RULE_1 AND GROUP_B_RULE_2) )" #. module: base #: model:ir.actions.act_window,help:base.action_ui_view @@ -1528,6 +1604,9 @@ msgid "" "Views allows you to personalize each view of OpenERP. You can add new " "fields, move fields, rename them or delete the ones that you do not need." msgstr "" +"Pogledi vam dovolijo prilagoditev vsak pogled OpenERP. Dodate lahko nova " +"polja, premaknite polja, jih preimenujete ali izbrišete tiste, ki jih ne " +"potrebujete." #. module: base #: field:ir.actions.act_window,groups_id:0 @@ -1553,7 +1632,7 @@ msgstr "Skupine" #. module: base #: selection:base.language.install,lang:0 msgid "Spanish (CL) / Español (CL)" -msgstr "" +msgstr "Špansko (CL) / Español (CL)" #. module: base #: view:res.config.users:0 @@ -1562,6 +1641,10 @@ msgid "" "access to selected functionalities within the system. Click on 'Done' if you " "do not wish to add more users at this stage, you can always do this later." msgstr "" +"Ustvarjajte dodatne uporabnike in jih dodelite skupinam, ki jim bodo " +"omogočila dostop do izbranih funkcij v sistemu. Kliknite na \"Končano\", če " +"ne želite dodati več uporabnikov na tej stopnji, lahko pa to naredite tudi " +"kasneje." #. module: base #: model:res.country,name:base.bz @@ -1584,17 +1667,19 @@ msgid "" "Comma-separated list of allowed view modes, such as 'form', 'tree', " "'calendar', etc. (Default: tree,form)" msgstr "" +"Z vejico ločen seznam dovoljenih načinov pogleda, kot so \"oblika\", " +"\"drevo\", \"koledar\", itd (Default: drevo, oblika)" #. module: base #: code:addons/orm.py:3147 #, python-format msgid "A document was modified since you last viewed it (%s:%d)" -msgstr "" +msgstr "Dokument je bil spremenjem po vašem zadnjem ogledu (%s:%d)" #. module: base #: view:workflow:0 msgid "Workflow Editor" -msgstr "" +msgstr "Urejevalnik delovnik procesov" #. module: base #: selection:ir.module.module,state:0 @@ -1614,6 +1699,9 @@ msgid "" "order in Object, and you can have loop on the sales order line. Expression = " "`object.order_line`." msgstr "" +"Vpišite polje / izraz, ki bo vrnil na seznam. Npr. izberite prodajo vrstni " +"red predmetov, in lahko imate zanko na vrstici prodajnega naročila. Izraz = " +"`object.order_line`." #. module: base #: field:ir.property,fields_id:0 @@ -1625,7 +1713,7 @@ msgstr "Polje" #. module: base #: view:ir.rule:0 msgid "Groups (no group = global)" -msgstr "" +msgstr "Skupine (ni skupine = globalno)" #. module: base #: model:res.country,name:base.fo @@ -1637,7 +1725,7 @@ msgstr "Ferski otoki" #: selection:res.config.view,view:0 #: selection:res.users,view:0 msgid "Simplified" -msgstr "" +msgstr "Poenostavljen" #. module: base #: model:res.country,name:base.st @@ -1652,7 +1740,7 @@ msgstr "Račun" #. module: base #: selection:base.language.install,lang:0 msgid "Portugese (BR) / Português (BR)" -msgstr "" +msgstr "Portugalsko (BR) / Português (BR)" #. module: base #: model:res.country,name:base.bb @@ -1670,7 +1758,7 @@ msgstr "Madagaskar" msgid "" "The Object name must start with x_ and not contain any special character !" msgstr "" -"Naziv objekta se mora začeti z 'x_' in ne sme vsebovati posebnih znakov." +"Naziv predmeta se mora začet z x_ in ne sme vsebovati posebnih znakov!" #. module: base #: field:ir.actions.configuration.wizard,note:0 @@ -1682,27 +1770,27 @@ msgstr "Naslednji čarovnik" #: view:ir.ui.menu:0 #: field:ir.ui.menu,name:0 msgid "Menu" -msgstr "Menu" +msgstr "Meni" #. module: base #: field:res.currency,rate:0 msgid "Current Rate" -msgstr "" +msgstr "Trenutno razmerje" #. module: base #: field:ir.ui.view.custom,ref_id:0 msgid "Original View" -msgstr "" +msgstr "Originalni pogled" #. module: base #: view:ir.values:0 msgid "Action To Launch" -msgstr "" +msgstr "Dejanje za zagon" #. module: base #: field:ir.actions.url,target:0 msgid "Action Target" -msgstr "" +msgstr "Cilj dejanja" #. module: base #: model:res.country,name:base.ai @@ -1725,6 +1813,8 @@ msgid "" "Provide the field name that the record id refers to for the write operation. " "If it is empty it will refer to the active id of the object." msgstr "" +"Navedite ime polja, ki se nanaša na zapis id za operacijo pisanja. Če je " +"prazna, se bo nanašalo na aktivni id predmeta." #. module: base #: model:res.country,name:base.zw @@ -1735,11 +1825,12 @@ msgstr "Zimbabve" #: view:base.module.update:0 msgid "Please be patient, as this operation may take a few seconds..." msgstr "" +"Prosimo, bodite potrpežljivi, saj lahko ta operacija traja nekaj sekund ..." #. module: base #: help:ir.values,action_id:0 msgid "This field is not used, it only helps you to select the right action." -msgstr "" +msgstr "Polje ni v uporabi, pomagam vas samo izbrati pravo dejanje." #. module: base #: field:ir.actions.server,email:0 @@ -1749,7 +1840,7 @@ msgstr "E-poštni naslov" #. module: base #: selection:base.language.install,lang:0 msgid "French (BE) / Français (BE)" -msgstr "" +msgstr "Francosko (BE) / Français (BE)" #. module: base #: view:ir.actions.server:0 @@ -1780,7 +1871,7 @@ msgstr "Preslikave polj" #. module: base #: view:base.language.export:0 msgid "Export Translations" -msgstr "" +msgstr "Izvoz prevodov" #. module: base #: model:ir.ui.menu,name:base.menu_custom @@ -1812,7 +1903,7 @@ msgstr "Litva" #: model:ir.model,name:base.model_partner_clear_ids #: view:partner.clear.ids:0 msgid "Clear IDs" -msgstr "" +msgstr "Počiši ID-je" #. module: base #: help:ir.cron,model:0 @@ -1820,17 +1911,19 @@ msgid "" "Name of object whose function will be called when this scheduler will run. " "e.g. 'res.partener'" msgstr "" +"Ime predmeta, katerih funkcija se bo klicalal, ko bo to tekel " +"razporejevalnik. npr. \"res.partener\"" #. module: base #: code:addons/orm.py:1040 #, python-format msgid "The perm_read method is not implemented on this object !" -msgstr "Metoda 'perm_read' ni implementirana za ta objekt." +msgstr "Metoda 'perm_read' ni implementirana za ta predmet!" #. module: base #: view:res.lang:0 msgid "%y - Year without century [00,99]." -msgstr "" +msgstr "%y - Leto brez stoletja [00,99]." #. module: base #: model:res.country,name:base.si @@ -1846,12 +1939,12 @@ msgstr "Pakistan" #: code:addons/orm.py:1350 #, python-format msgid "Invalid Object Architecture!" -msgstr "" +msgstr "Neveljavna arhitektura predmeta!" #. module: base #: model:ir.ui.menu,name:base.menu_email_gateway_form msgid "Messages" -msgstr "" +msgstr "Sporočila" #. module: base #: code:addons/base/ir/ir_model.py:303 @@ -1868,17 +1961,17 @@ msgstr "Napaka!" #. module: base #: view:res.lang:0 msgid "%p - Equivalent of either AM or PM." -msgstr "" +msgstr "%p - ekvivalenten bodisi AM ali PM." #. module: base #: view:ir.actions.server:0 msgid "Iteration Actions" -msgstr "" +msgstr "Ponovitvena dejanja" #. module: base #: help:multi_company.default,company_id:0 msgid "Company where the user is connected" -msgstr "" +msgstr "Podjetje kamor je uporabnik povezan" #. module: base #: field:publisher_warranty.contract,date_stop:0 @@ -1897,6 +1990,8 @@ msgid "" "One of the records you are trying to modify has already been deleted " "(Document type: %s)." msgstr "" +"Eden izmed zapisov, ki jih poskušate spremeniti, so že izbrisana (Vrsta " +"dokumenta: %s)." #. module: base #: model:ir.actions.act_window,help:base.action_country @@ -1905,6 +2000,9 @@ msgid "" "partner records. You can create or delete countries to make sure the ones " "you are working on will be maintained." msgstr "" +"Prikaz in upravljanje seznam vseh držav, ki jih je mogoče dodeliti vašemu " +"zapisu partnerja. Lahko ustvarite ali izbrišete države, da se prepričate, da " +"tisti s katerimi delate, da so vzdrževani." #. module: base #: model:res.partner.category,name:base.res_partner_category_7 @@ -1919,18 +2017,18 @@ msgstr "Otok Norfolk" #. module: base #: selection:base.language.install,lang:0 msgid "Korean (KR) / 한국어 (KR)" -msgstr "" +msgstr "Korejsko (KR) / 한국어 (KR)" #. module: base #: help:ir.model.fields,model:0 msgid "The technical name of the model this field belongs to" -msgstr "" +msgstr "Tehnično ime modela h kateremu to polje pripada" #. module: base #: field:ir.actions.server,action_id:0 #: selection:ir.actions.server,state:0 msgid "Client Action" -msgstr "Odjemalčeva akcija" +msgstr "Klientovo dejanje" #. module: base #: model:res.country,name:base.bd @@ -1940,7 +2038,7 @@ msgstr "Bangladeš" #. module: base #: constraint:res.company:0 msgid "Error! You can not create recursive companies." -msgstr "Napaka. Ne morete ustvariti rekurzivnih družb." +msgstr "Napaka! Ne morete ustvariti rekurzivnih podjetij." #. module: base #: selection:publisher_warranty.contract,state:0 @@ -1971,7 +2069,7 @@ msgstr "res.partner.event" #. module: base #: model:res.widget,title:base.facebook_widget msgid "Facebook" -msgstr "" +msgstr "Facebook" #. module: base #: model:res.country,name:base.am @@ -1982,12 +2080,12 @@ msgstr "Armenija" #: model:ir.actions.act_window,name:base.ir_property_form #: model:ir.ui.menu,name:base.menu_ir_property_form_all msgid "Configuration Parameters" -msgstr "" +msgstr "Parametri konfiguracije" #. module: base #: constraint:ir.cron:0 msgid "Invalid arguments" -msgstr "" +msgstr "Neveljavni argumenti" #. module: base #: model:res.country,name:base.se @@ -2027,17 +2125,17 @@ msgstr "Vrsta bančnega računa" #: field:res.config.users,config_logo:0 #: field:res.config.view,config_logo:0 msgid "Image" -msgstr "" +msgstr "Slika" #. module: base #: view:ir.actions.server:0 msgid "Iteration Action Configuration" -msgstr "" +msgstr "Konfiguracija ponovitvenega dejanja" #. module: base #: selection:publisher_warranty.contract,state:0 msgid "Canceled" -msgstr "" +msgstr "Preklicano" #. module: base #: model:res.country,name:base.at @@ -2062,7 +2160,7 @@ msgstr "Koledar" #. module: base #: field:res.partner.address,partner_id:0 msgid "Partner Name" -msgstr "" +msgstr "Ime partnerja" #. module: base #: field:workflow.activity,signal_send:0 @@ -2072,7 +2170,7 @@ msgstr "" #. module: base #: model:res.partner.category,name:base.res_partner_category_17 msgid "HR sector" -msgstr "" +msgstr "Sektor HR" #. module: base #: code:addons/orm.py:3817 @@ -2082,6 +2180,9 @@ msgid "" "separated list of valid field names (optionally followed by asc/desc for the " "direction)" msgstr "" +"Navedeno neveljavno \"naročilo\" Veljavna specifikacija \"naročila\" je z " +"vejico ločen seznam veljavnih imen polj (opcijsko za smetri sledi " +"naraščajoče/padajoče)" #. module: base #: model:ir.model,name:base.model_ir_module_module_dependency @@ -2098,7 +2199,7 @@ msgstr "Osnutek" #: selection:res.config.view,view:0 #: selection:res.users,view:0 msgid "Extended" -msgstr "" +msgstr "Razširjeno" #. module: base #: model:ir.actions.act_window,help:base.action_partner_title_contact @@ -2107,6 +2208,9 @@ msgid "" "way you want to print them in letters and other documents. Some example: " "Mr., Mrs. " msgstr "" +"Upravljanje kontaktnih naslovov, ki jih želite imeti na voljo v vašem " +"sistemu in tako, kot želite, da jih natisnete na pisma in druge dokumente " +"Nekateri primere: gospod, gospa. " #. module: base #: field:res.company,rml_footer1:0 @@ -2134,12 +2238,12 @@ msgstr "Odvisnosti" #. module: base #: field:multi_company.default,company_id:0 msgid "Main Company" -msgstr "Glavna družba" +msgstr "Glavno podjetje" #. module: base #: field:ir.ui.menu,web_icon_hover:0 msgid "Web Icon File (hover)" -msgstr "" +msgstr "Datoteka spletne ikone (hover)" #. module: base #: view:ir.actions.server:0 @@ -2147,6 +2251,8 @@ msgid "" "If you use a formula type, use a python expression using the variable " "'object'." msgstr "" +"Če uporabite tip formule, uporabite python izraz z uporabo spremenljivke " +"'object'." #. module: base #: field:res.partner.address,birthdate:0 @@ -2157,7 +2263,7 @@ msgstr "Datum rojstva" #: model:ir.actions.act_window,name:base.action_partner_title_contact #: model:ir.ui.menu,name:base.menu_partner_title_contact msgid "Contact Titles" -msgstr "" +msgstr "Naziv kontakta" #. module: base #: view:base.language.import:0 @@ -2165,11 +2271,13 @@ msgid "" "Please double-check that the file encoding is set to UTF-8 (sometimes called " "Unicode) when the translator exports it." msgstr "" +"Prosimo, še enkrat preverite, da je nastavljeno za datoteko kodiranje UTF-8 " +"(včasih se imenuje Unicode), ko je prevajalec izvozi." #. module: base #: selection:base.language.install,lang:0 msgid "Spanish (DO) / Español (DO)" -msgstr "" +msgstr "Špansko (DO) / Español (DO)" #. module: base #: model:ir.model,name:base.model_workflow_activity @@ -2182,11 +2290,13 @@ msgid "" "Reference of the target resource, whose model/table depends on the 'Resource " "Name' field." msgstr "" +"Sklic ciljnega vira, katerega model / tabela je odvisno od polja \"Ime " +"vira\"." #. module: base #: field:ir.model.fields,select_level:0 msgid "Searchable" -msgstr "" +msgstr "Možno iskati" #. module: base #: model:res.country,name:base.uy @@ -2196,12 +2306,12 @@ msgstr "Urugvaj" #. module: base #: selection:base.language.install,lang:0 msgid "Finnish / Suomi" -msgstr "" +msgstr "Finsko / Suomi" #. module: base #: field:ir.rule,perm_write:0 msgid "Apply For Write" -msgstr "" +msgstr "Uporabi za pisanje" #. module: base #: field:ir.sequence,prefix:0 @@ -2211,12 +2321,12 @@ msgstr "Predpona" #. module: base #: selection:base.language.install,lang:0 msgid "German / Deutsch" -msgstr "" +msgstr "Nemško / Deutsch" #. module: base #: help:ir.actions.server,trigger_name:0 msgid "Select the Signal name that is to be used as the trigger." -msgstr "" +msgstr "Izberite ime signala, ki bo uporabljeno za sprožilec." #. module: base #: view:ir.actions.server:0 @@ -2226,7 +2336,7 @@ msgstr "Preslikava polj" #. module: base #: selection:base.language.install,lang:0 msgid "Portugese / Português" -msgstr "" +msgstr "Portugalsko/ Português" #. module: base #: model:res.partner.title,name:base.res_partner_title_sir @@ -2237,7 +2347,7 @@ msgstr "Gospod" #: code:addons/orm.py:1622 #, python-format msgid "There is no view of type '%s' defined for the structure!" -msgstr "" +msgstr "Ni navedeno vrste pogleda '%s' za strukturo!" #. module: base #: field:ir.default,ref_id:0 @@ -2248,7 +2358,7 @@ msgstr "Sklic ID" #: model:ir.actions.server,name:base.action_start_configurator #: model:ir.ui.menu,name:base.menu_view_base_module_configuration msgid "Start Configuration" -msgstr "" +msgstr "Začni s konfiguracijo" #. module: base #: model:res.country,name:base.mt @@ -2258,7 +2368,7 @@ msgstr "Malta" #. module: base #: field:ir.actions.server,fields_lines:0 msgid "Field Mappings." -msgstr "" +msgstr "Preslikave polj" #. module: base #: model:ir.model,name:base.model_ir_module_module @@ -2286,7 +2396,7 @@ msgstr "Opis" #: model:ir.actions.act_window,name:base.action_workflow_instance_form #: model:ir.ui.menu,name:base.menu_workflow_instance msgid "Instances" -msgstr "Pojavitve" +msgstr "Primeri" #. module: base #: model:res.country,name:base.aq @@ -2296,12 +2406,12 @@ msgstr "Antarktika" #. module: base #: field:ir.actions.report.xml,auto:0 msgid "Custom python parser" -msgstr "" +msgstr "Python parser po meri" #. module: base #: view:base.language.import:0 msgid "_Import" -msgstr "" +msgstr "_Uvozi" #. module: base #: view:res.partner.canal:0 @@ -2311,17 +2421,17 @@ msgstr "Kanal" #. module: base #: field:res.lang,grouping:0 msgid "Separator Format" -msgstr "" +msgstr "Oblika ločila" #. module: base #: selection:publisher_warranty.contract,state:0 msgid "Unvalidated" -msgstr "" +msgstr "Ni potrjeno" #. module: base #: model:ir.ui.menu,name:base.next_id_9 msgid "Database Structure" -msgstr "Struktura skladišča podatkov" +msgstr "Struktura podatkovne baze" #. module: base #: model:ir.actions.act_window,name:base.action_partner_mass_mail @@ -2339,7 +2449,7 @@ msgstr "Mayotte" #: code:addons/base/ir/ir_actions.py:597 #, python-format msgid "Please specify an action to launch !" -msgstr "" +msgstr "Prosim, navedite dejanje za zagon!" #. module: base #: view:res.payterm:0 @@ -2349,7 +2459,7 @@ msgstr "Plačilni pogoj" #. module: base #: selection:res.lang,direction:0 msgid "Right-to-Left" -msgstr "" +msgstr "Z desne na levo" #. module: base #: view:ir.actions.act_window:0 @@ -2358,7 +2468,7 @@ msgstr "" #: model:ir.model,name:base.model_ir_filters #: model:ir.ui.menu,name:base.menu_ir_filters msgid "Filters" -msgstr "" +msgstr "Filtri" #. module: base #: code:addons/orm.py:758 @@ -2371,31 +2481,31 @@ msgstr "Preverite, če imajo vse vaše vrstice %d stolpcev." #: view:ir.cron:0 #: model:ir.ui.menu,name:base.menu_ir_cron_act msgid "Scheduled Actions" -msgstr "Planirane akcije" +msgstr "Planirana dejanja" #. module: base #: field:res.partner.address,title:0 #: field:res.partner.title,name:0 #: field:res.widget,title:0 msgid "Title" -msgstr "Titula" +msgstr "Naziv" #. module: base #: help:ir.property,res_id:0 msgid "If not set, acts as a default value for new resources" -msgstr "" +msgstr "Če ni nastavljeno, se obnaša kot privzera vrednost za nove vire" #. module: base #: code:addons/orm.py:3448 #, python-format msgid "Recursivity Detected." -msgstr "" +msgstr "Zaznana rekurzivnost." #. module: base #: code:addons/base/module/module.py:262 #, python-format msgid "Recursion error in modules dependencies !" -msgstr "Napaka rekurzije v odvisnostih modulov." +msgstr "Napaka rekurzije v odvisnostih modulih!" #. module: base #: view:base.language.install:0 @@ -2404,11 +2514,14 @@ msgid "" "loading a new language it becomes available as default interface language " "for users and partners." msgstr "" +"Ta čarovnik vam pomaga pri dodajanju novega jezika v vaš OpenERP sistem. Po " +"nalaganju novega jezika, postane dostopen kot privzeti jezik vmesnika vašim " +"uporabnikom in partnerjem." #. module: base #: view:ir.model:0 msgid "Create a Menu" -msgstr "Ustvari menu" +msgstr "Ustvari meni" #. module: base #: help:res.partner,vat:0 @@ -2416,11 +2529,13 @@ msgid "" "Value Added Tax number. Check the box if the partner is subjected to the " "VAT. Used by the VAT legal statement." msgstr "" +"Številka davka na dodano vrednost. Preverite polje, če je partner predmet " +"DDV. Uporabljeno za DDV pravno izjavo." #. module: base #: model:ir.model,name:base.model_maintenance_contract msgid "maintenance.contract" -msgstr "" +msgstr "maintenance.contract" #. module: base #: model:res.country,name:base.ru @@ -2435,7 +2550,7 @@ msgstr "" #. module: base #: field:res.company,name:0 msgid "Company Name" -msgstr "Naziv družbe" +msgstr "Ime podjetja" #. module: base #: model:ir.actions.act_window,name:base.action_country @@ -2446,7 +2561,7 @@ msgstr "Države" #. module: base #: selection:ir.translation,type:0 msgid "RML (deprecated - use Report)" -msgstr "" +msgstr "RML (opuščeno - uporabite Poročilo)" #. module: base #: view:ir.rule:0 @@ -2456,43 +2571,43 @@ msgstr "Posnemi pravila" #. module: base #: view:ir.property:0 msgid "Field Information" -msgstr "" +msgstr "Podatki polja" #. module: base #: view:ir.actions.todo:0 msgid "Search Actions" -msgstr "" +msgstr "Dejanje iskanja" #. module: base #: model:ir.actions.act_window,name:base.action_view_partner_wizard_ean_check #: view:partner.wizard.ean.check:0 msgid "Ean check" -msgstr "" +msgstr "Preveri ean" #. module: base #: field:res.partner,vat:0 msgid "VAT" -msgstr "DDV ID" +msgstr "DDV" #. module: base #: view:res.lang:0 msgid "12. %w ==> 5 ( Friday is the 6th day)" -msgstr "" +msgstr "12. %w ==> (Petek je šesti dan)" #. module: base #: constraint:res.partner.category:0 msgid "Error ! You can not create recursive categories." -msgstr "Napaka! Ne morete ustvariti rekurzivne kategorije." +msgstr "Napaka! Rekurzivnih kategorij ne morete ustvariti." #. module: base #: view:res.lang:0 msgid "%x - Appropriate date representation." -msgstr "" +msgstr "%x - Ustrezen datum zastopanja." #. module: base #: view:res.lang:0 msgid "%d - Day of the month [01,31]." -msgstr "" +msgstr "%d - Dan v mesecu [01,31]." #. module: base #: model:res.country,name:base.tj @@ -2502,12 +2617,12 @@ msgstr "Tadžikistan" #. module: base #: selection:ir.module.module,license:0 msgid "GPL-2 or later version" -msgstr "" +msgstr "GPL-2 ali naslednja verzija" #. module: base #: model:res.partner.title,shortcut:base.res_partner_title_sir msgid "M." -msgstr "" +msgstr "G." #. module: base #: code:addons/base/module/module.py:429 @@ -2526,17 +2641,19 @@ msgid "" "Operation prohibited by access rules, or performed on an already deleted " "document (Operation: read, Document type: %s)." msgstr "" +"Operacijo prepovedujejo dostopna pravila, ali se izvajajo na že izbrisanem " +"dokumentnu (Operacija: branje, vrsta dokumenta: %s)." #. module: base #: model:res.country,name:base.nr msgid "Nauru" -msgstr "" +msgstr "Nauru" #. module: base #: code:addons/base/module/module.py:200 #, python-format msgid "The certificate ID of the module must be unique !" -msgstr "" +msgstr "ID potrdila modula mora biti edinstven!" #. module: base #: model:ir.model,name:base.model_ir_property @@ -2560,7 +2677,7 @@ msgstr "Črna gora" #. module: base #: view:ir.cron:0 msgid "Technical Data" -msgstr "" +msgstr "Tehnični podatki" #. module: base #: view:res.partner:0 @@ -2575,13 +2692,15 @@ msgid "" "import a language pack from here. Other OpenERP languages than the official " "ones can be found on launchpad." msgstr "" +"Če potrebujete drug jezik, ki je uradno dostopen, ga lahko tukaj uvozite. " +"Ostali OpenERP jeziki, ki niso uradni, so dostopni na launchpad." #. module: base #: view:ir.module.module:0 #: selection:ir.module.module,state:0 #: selection:ir.module.module.dependency,state:0 msgid "To be upgraded" -msgstr "Za nadgraditi" +msgstr "Bo nadgrajeno" #. module: base #: model:res.country,name:base.ly @@ -2596,7 +2715,7 @@ msgstr "Centralnoafriška republika" #. module: base #: model:res.country,name:base.li msgid "Liechtenstein" -msgstr "" +msgstr "Liechtenstein" #. module: base #: model:ir.model,name:base.model_partner_sms_send @@ -2613,7 +2732,7 @@ msgstr "Črtna koda (EAN13)" #: code:addons/orm.py:1622 #, python-format msgid "Invalid Architecture!" -msgstr "" +msgstr "Neveljavna arhitektura" #. module: base #: model:res.country,name:base.pt @@ -2624,12 +2743,12 @@ msgstr "Portugalska" #: sql_constraint:ir.model.data:0 msgid "" "You cannot have multiple records with the same id for the same module !" -msgstr "" +msgstr "Ne morete imeti več zapisov z istim id za isti modul!" #. module: base #: field:ir.module.module,certificate:0 msgid "Quality Certificate" -msgstr "" +msgstr "Potrdilo kakovosti" #. module: base #: view:res.lang:0 @@ -2640,17 +2759,17 @@ msgstr "6. %d, %m ==> 05, 12" #: field:res.config.users,date:0 #: field:res.users,date:0 msgid "Last Connection" -msgstr "" +msgstr "Zadnja povezava" #. module: base #: field:ir.actions.act_window,help:0 msgid "Action description" -msgstr "" +msgstr "Opis dejanja" #. module: base #: help:res.partner,customer:0 msgid "Check this box if the partner is a customer." -msgstr "" +msgstr "Označite to polje, če je partner stranka." #. module: base #: model:ir.actions.act_window,name:base.res_lang_act_window @@ -2664,7 +2783,7 @@ msgstr "Jeziki" #: selection:workflow.activity,join_mode:0 #: selection:workflow.activity,split_mode:0 msgid "Xor" -msgstr "Izključujoči ALI" +msgstr "Xor" #. module: base #: model:res.country,name:base.ec @@ -2689,7 +2808,7 @@ msgstr "" #: model:ir.ui.menu,name:base.menu_partner_form #: view:res.partner:0 msgid "Customers" -msgstr "" +msgstr "Stranke" #. module: base #: model:res.country,name:base.au @@ -2718,12 +2837,12 @@ msgstr "Osnovno polje" #. module: base #: view:publisher_warranty.contract:0 msgid "Validate" -msgstr "" +msgstr "Preveri" #. module: base #: field:ir.actions.todo,restart:0 msgid "Restart" -msgstr "" +msgstr "Ponoven zagon" #. module: base #: field:ir.actions.report.xml,report_sxw_content:0 @@ -2740,13 +2859,15 @@ msgstr "Čarovnik" #. module: base #: view:ir.cron:0 msgid "Action to Trigger" -msgstr "" +msgstr "Dejanje za zagon" #. module: base #: code:addons/base/res/res_user.py:136 #, python-format msgid "\"email_from\" needs to be set to send welcome mails to users" msgstr "" +"\"email_form\" mora biti nastavljen za pošiljanje e-pošte dobrodošlice " +"uporabnikom" #. module: base #: selection:ir.translation,type:0 @@ -2764,12 +2885,12 @@ msgstr "Privzeto" #: field:ir.model.fields,required:0 #: field:res.partner.bank.type.field,required:0 msgid "Required" -msgstr "Obvezno" +msgstr "Zahtevano" #. module: base #: view:res.users:0 msgid "Default Filters" -msgstr "" +msgstr "Privzeti filtri" #. module: base #: field:res.request.history,name:0 @@ -2779,7 +2900,7 @@ msgstr "Povzetek" #. module: base #: field:multi_company.default,expression:0 msgid "Expression" -msgstr "" +msgstr "Izraz" #. module: base #: help:ir.actions.server,subject:0 @@ -2787,6 +2908,8 @@ msgid "" "Specify the subject. You can use fields from the object, e.g. `Hello [[ " "object.partner_id.name ]]`" msgstr "" +"Navedite predmet. Uporabite lahko polja iz predmeta, npr. 'Pozdravljeni " +"[[object.partner_id.name]]'" #. module: base #: view:res.company:0 @@ -2799,6 +2922,8 @@ msgid "" "Optional help text for the users with a description of the target view, such " "as its usage and purpose." msgstr "" +"Opcijski teksti pomoči za uporabnike z opisi ciljnega pogleda, kot je " +"uporaba in namen." #. module: base #: model:res.country,name:base.va @@ -2813,28 +2938,28 @@ msgstr ".ZIP datoteka modula" #. module: base #: field:ir.ui.view,xml_id:0 msgid "XML ID" -msgstr "" +msgstr "ID XML" #. module: base #: model:res.partner.category,name:base.res_partner_category_16 msgid "Telecom sector" -msgstr "" +msgstr "Sektor telekom" #. module: base #: field:workflow.transition,trigger_model:0 msgid "Trigger Object" -msgstr "" +msgstr "Predmet sprožilca" #. module: base #: view:res.users:0 msgid "Current Activity" -msgstr "" +msgstr "Trenutna aktivnost" #. module: base #: view:workflow.activity:0 #: field:workflow.activity,in_transitions:0 msgid "Incoming Transitions" -msgstr "" +msgstr "Prihajajočite transakcije" #. module: base #: model:res.country,name:base.sr @@ -2844,7 +2969,7 @@ msgstr "Surinam" #. module: base #: model:ir.ui.menu,name:base.marketing_menu msgid "Marketing" -msgstr "" +msgstr "Marketing" #. module: base #: view:res.partner.bank:0 @@ -2855,7 +2980,7 @@ msgstr "Bančni račun" #. module: base #: selection:base.language.install,lang:0 msgid "Spanish (HN) / Español (HN)" -msgstr "" +msgstr "Špansko (HN) / Español (HN)" #. module: base #: view:ir.sequence.type:0 @@ -2865,7 +2990,7 @@ msgstr "Vrsta zaporedja" #. module: base #: view:ir.ui.view.custom:0 msgid "Customized Architecture" -msgstr "" +msgstr "Prilagojena arhitektura" #. module: base #: field:ir.module.module,license:0 @@ -2875,17 +3000,17 @@ msgstr "Licenca" #. module: base #: field:ir.attachment,url:0 msgid "Url" -msgstr "" +msgstr "Url" #. module: base #: selection:ir.actions.todo,restart:0 msgid "Always" -msgstr "" +msgstr "Vedno" #. module: base #: selection:ir.translation,type:0 msgid "SQL Constraint" -msgstr "" +msgstr "SQL omejitve" #. module: base #: field:ir.actions.server,srcmodel_id:0 @@ -2899,11 +3024,13 @@ msgid "" "The selected language has been successfully installed. You must change the " "preferences of the user and open a new menu to view the changes." msgstr "" +"Izbrani jezik je bil uspešno nameščen. Spremeniti morate lasnosti uporabnika " +"in odpreti nov meni za ogled sprememb." #. module: base #: sql_constraint:ir.config_parameter:0 msgid "Key must be unique." -msgstr "" +msgstr "Ključ mora biti edinstven." #. module: base #: view:ir.actions.act_window:0 @@ -2919,7 +3046,7 @@ msgstr "Ekvatorialna Gvineja" #: view:base.module.import:0 #: model:ir.actions.act_window,name:base.action_view_base_module_import msgid "Module Import" -msgstr "" +msgstr "Uvoz modula" #. module: base #: field:res.bank,zip:0 @@ -2937,12 +3064,12 @@ msgstr "Avtor" #. module: base #: model:res.country,name:base.mk msgid "FYROM" -msgstr "" +msgstr "FYROM" #. module: base #: view:res.lang:0 msgid "%c - Appropriate date and time representation." -msgstr "" +msgstr "%c - Ustrezni datum in čas zastopanja." #. module: base #: code:addons/base/res/res_config.py:422 @@ -2952,11 +3079,14 @@ msgid "" "\n" "Click 'Continue' and enjoy your OpenERP experience..." msgstr "" +"Vaša podatkovna baza je v celoti konfigurirana.\n" +"\n" +"Kliknite 'Nadaljuj' in uživajte v izkušnji OpenERP..." #. module: base #: selection:base.language.install,lang:0 msgid "Hebrew / עִבְרִי" -msgstr "" +msgstr "Židovsko / עִבְרִי" #. module: base #: model:res.country,name:base.bo @@ -2999,12 +3129,12 @@ msgstr "Poskušate odstraniti modul, ki je nameščen ali bo nameščen" #. module: base #: view:base.module.upgrade:0 msgid "The selected modules have been updated / installed !" -msgstr "" +msgstr "Izbrani moduli so bili posodobljeni / nameščeni!" #. module: base #: selection:base.language.install,lang:0 msgid "Spanish (PR) / Español (PR)" -msgstr "" +msgstr "Špansko (PR) / Español (PR)" #. module: base #: model:res.country,name:base.gt @@ -3017,17 +3147,17 @@ msgstr "Gvatemala" #: model:ir.ui.menu,name:base.menu_workflow #: model:ir.ui.menu,name:base.menu_workflow_root msgid "Workflows" -msgstr "Poteki dela" +msgstr "Delovni procesi" #. module: base #: field:ir.translation,xml_id:0 msgid "XML Id" -msgstr "" +msgstr "Id XML" #. module: base #: model:ir.actions.act_window,name:base.action_config_user_form msgid "Create Users" -msgstr "" +msgstr "Ustvari uporabnike" #. module: base #: model:ir.model,name:base.model_res_partner_title @@ -3037,12 +3167,12 @@ msgstr "res.partner.title" #. module: base #: view:ir.values:0 msgid "tree_but_action, client_print_multi" -msgstr "" +msgstr "Copy text \t tree_but_action, client_print_multi" #. module: base #: model:res.partner.category,name:base.res_partner_category_retailers0 msgid "Retailers" -msgstr "" +msgstr "Trgovci na drobno" #. module: base #: help:ir.cron,priority:0 @@ -3068,7 +3198,7 @@ msgstr "Lesoto" #: code:addons/base/ir/ir_model.py:114 #, python-format msgid "You can not remove the model '%s' !" -msgstr "Ne morete odstraniti modela '%s'." +msgstr "Ne morete odstraniti modela '%s'!" #. module: base #: model:res.country,name:base.ke @@ -3078,12 +3208,12 @@ msgstr "Kenija" #. module: base #: view:res.partner.event:0 msgid "Event" -msgstr "" +msgstr "Dogodek" #. module: base #: model:ir.ui.menu,name:base.menu_custom_reports msgid "Custom Reports" -msgstr "" +msgstr "Poročila po meri" #. module: base #: selection:base.language.install,lang:0 @@ -3093,18 +3223,18 @@ msgstr "" #. module: base #: view:base.module.configuration:0 msgid "System Configuration Done" -msgstr "" +msgstr "Konfiguracija sistema končana" #. module: base #: code:addons/orm.py:929 #, python-format msgid "Error occurred while validating the field(s) %s: %s" -msgstr "" +msgstr "Napaka se je pojavila med preverjanjem polj %s: %s" #. module: base #: view:ir.property:0 msgid "Generic" -msgstr "" +msgstr "Splošno" #. module: base #: model:res.country,name:base.sm @@ -3135,17 +3265,17 @@ msgstr "Benin" #: code:addons/base/publisher_warranty/publisher_warranty.py:281 #, python-format msgid "That contract is already registered in the system." -msgstr "" +msgstr "Ta pogodba je že registrirana v sistemu." #. module: base #: help:ir.sequence,suffix:0 msgid "Suffix value of the record for the sequence" -msgstr "" +msgstr "Pripona vrednosti zapisa za zaporedje" #. module: base #: selection:base.language.install,lang:0 msgid "Spanish (PY) / Español (PY)" -msgstr "" +msgstr "Špansko (PY) / Español (PY)" #. module: base #: field:ir.config_parameter,key:0 @@ -3169,17 +3299,19 @@ msgid "" "You can not create this document (%s) ! Be sure your user belongs to one of " "these groups: %s." msgstr "" +"Ne morete ustvariti tega dokumenta (%s)! Bodite prepričani, da vaš " +"uporabnik pripada tem skupinam: %s." #. module: base #: model:res.country,name:base.mu msgid "Mauritius" -msgstr "" +msgstr "Mauricius" #. module: base #: view:ir.model.access:0 #: view:ir.rule:0 msgid "Full Access" -msgstr "" +msgstr "Polni dostop" #. module: base #: view:ir.actions.act_window:0 @@ -3193,7 +3325,7 @@ msgstr "Varnost" #. module: base #: model:res.widget,title:base.openerp_favorites_twitter_widget msgid "OpenERP Favorites" -msgstr "" +msgstr "OpenERP priljubljene" #. module: base #: model:res.country,name:base.za @@ -3210,13 +3342,13 @@ msgstr "Namščen" #. module: base #: selection:base.language.install,lang:0 msgid "Ukrainian / українська" -msgstr "" +msgstr "Ukrajinsko / українська" #. module: base #: model:ir.actions.act_window,name:base.action_translation #: model:ir.ui.menu,name:base.menu_action_translation msgid "Translation Terms" -msgstr "" +msgstr "Pogoji prevodov" #. module: base #: model:res.country,name:base.sn @@ -3241,12 +3373,12 @@ msgstr "Brazilija" #. module: base #: view:res.lang:0 msgid "%M - Minute [00,59]." -msgstr "" +msgstr "%M - Minute [00,59]." #. module: base #: selection:ir.module.module,license:0 msgid "Affero GPL-3" -msgstr "" +msgstr "Affero GPL-3" #. module: base #: field:ir.sequence,number_next:0 @@ -3256,12 +3388,12 @@ msgstr "Naslednja številka" #. module: base #: help:workflow.transition,condition:0 msgid "Expression to be satisfied if we want the transition done." -msgstr "" +msgstr "Izraz, ki ja treba izpolniti, če želimo izpolniti transakcijo." #. module: base #: selection:base.language.install,lang:0 msgid "Spanish (PA) / Español (PA)" -msgstr "" +msgstr "Špansko (PA) / Español (PA)" #. module: base #: view:res.currency:0 @@ -3286,11 +3418,14 @@ msgid "" "invoice, then `object.invoice_address_id.mobile` is the field which gives " "the correct mobile number" msgstr "" +"Zagotavlja polja, ki se uporablja za pridobivanje mobilne številke, npr, " +"izberete račun, nato pa polje `object.invoice_address_id.mobile`, ki daje " +"pravo mobilno številko" #. module: base #: view:base.module.upgrade:0 msgid "System update completed" -msgstr "" +msgstr "Posodobitev sistema je končano" #. module: base #: selection:res.request,state:0 @@ -3321,28 +3456,28 @@ msgstr "Podatki" #: field:ir.ui.menu,parent_id:0 #: field:wizard.ir.model.menu.create,menu_id:0 msgid "Parent Menu" -msgstr "Nadmenu" +msgstr "Nameni" #. module: base #: field:ir.rule,perm_unlink:0 msgid "Apply For Delete" -msgstr "" +msgstr "Uporabi za izbris" #. module: base #: code:addons/base/ir/ir_model.py:319 #, python-format msgid "Cannot rename column to %s, because that column already exists!" -msgstr "" +msgstr "Ne morem preimenovati stolpca v %s, ker ta stolpec že obstaja." #. module: base #: view:ir.attachment:0 msgid "Attached To" -msgstr "" +msgstr "Pripeto k" #. module: base #: field:res.lang,decimal_point:0 msgid "Decimal Separator" -msgstr "" +msgstr "Decimalni ločevalnik" #. module: base #: model:ir.actions.act_window,help:base.action_res_groups @@ -3354,6 +3489,12 @@ msgid "" "to see. Whether they can have a read, write, create and delete access right " "can be managed from here." msgstr "" +"Skupina je nabor funkcionalnih območij, ki bodo dodeljene uporabniku, da se " +"jim omogoči dostop in pravice do specifičnih aplikacij in nalog v sistemu. " +"Lahko ustvarite skupine po meri ali uredite tiste, ki veljajo privzeto, da " +"si prilagodite pogled menija, ki ga bodo uporabniki lahko videli. Ali lahko " +"imajo pravice za dosotp do branje, pisanje, ustvarjanje in brisanje, lahko " +"upravljate od tukaj." #. module: base #: view:res.partner:0 @@ -3377,6 +3518,12 @@ msgid "" "Would your payment have been carried out after this mail was sent, please " "consider the present one as void." msgstr "" +"Prosimo, upoštevajte, da so naslednja plačila sedaj na vrsti. Če je bilo " +"poslano vaše plačilo, prosimo, posredujte vaše podatke plačila. Če bo " +"plačilo dodatno zamudilo, se prosim obrnite na nas glede tega. " +" \n" +"Če je bilo vaše plačilo izvedeno po tem, ko je bil poslano to sporočilo, " +"prosimo, obravnavajte prejšnjega kot neveljavnega." #. module: base #: model:res.country,name:base.mx @@ -3386,12 +3533,12 @@ msgstr "Mehika" #. module: base #: model:ir.ui.menu,name:base.menu_base_config_plugins msgid "Plugins" -msgstr "" +msgstr "Vtičniki" #. module: base #: field:res.company,child_ids:0 msgid "Child Companies" -msgstr "Hčerinske družbe" +msgstr "Hčerinska podjetja" #. module: base #: model:ir.model,name:base.model_res_users @@ -3407,7 +3554,7 @@ msgstr "Nikaragva" #: code:addons/orm.py:1046 #, python-format msgid "The write method is not implemented on this object !" -msgstr "Metoda 'write' ni implementirana za ta objekt." +msgstr "Metoda 'write' ni implementirana za ta predmet!" #. module: base #: view:res.partner.event:0 @@ -3418,7 +3565,7 @@ msgstr "Splošni opis" #: model:ir.actions.act_window,name:base.action_config_simple_view_form #: view:res.config.view:0 msgid "Configure Your Interface" -msgstr "" +msgstr "Nastavite vaš vmesnik" #. module: base #: field:ir.values,meta:0 @@ -3428,7 +3575,7 @@ msgstr "Meta podatki" #. module: base #: sql_constraint:ir.ui.view_sc:0 msgid "Shortcut for this menu already exists!" -msgstr "" +msgstr "Bližnjica za ta meni že obstaja!" #. module: base #: model:res.country,name:base.ve @@ -3456,7 +3603,7 @@ msgstr "" #. module: base #: field:res.partner,parent_id:0 msgid "Parent Partner" -msgstr "" +msgstr "Matični partner" #. module: base #: view:ir.module.module:0 @@ -3476,7 +3623,7 @@ msgstr "Kazahstan" #. module: base #: view:res.lang:0 msgid "%w - Weekday number [0(Sunday),6]." -msgstr "" +msgstr "%w - Številka dneva v tednu [0(nedelja),6]" #. module: base #: model:ir.actions.act_window,help:base.action_partner_form @@ -3489,6 +3636,13 @@ msgid "" "plugin, don't forget to register emails to each contact so that the gateway " "will automatically attach incoming emails to the right partner." msgstr "" +"Stranka je bistvo s katerim poslujete, kot podjetje ali organizacija. " +"Stranka ima lahko več kontaktov ali naslovov, ki so ljudje, kateri delajo za " +"t o podjetje. Lahko uporabite zavihek zgodovina, za spremljanje vseh " +"transakcij stranke, prodajna naročila, e-pošta, priložnosti, pritožbe, itd. " +"Če uporabljate e-poštni prehod, vtičnik Outlook ali Thunderbird, ne pozabite " +"registrirati e-pošte vsakemu kontaktu, tako da bo prehod avtomatsko pripel e-" +"pošte k pravemu partnerju." #. module: base #: field:ir.actions.report.xml,name:0 @@ -3516,7 +3670,7 @@ msgstr "" #: field:workflow,name:0 #: field:workflow.activity,name:0 msgid "Name" -msgstr "Naziv" +msgstr "Ime" #. module: base #: help:ir.actions.act_window,multi:0 @@ -3524,6 +3678,8 @@ msgid "" "If set to true, the action will not be displayed on the right toolbar of a " "form view" msgstr "" +"Če je nastavljeno na true, dejanje ne bo prikazano v desni orodni vrstici " +"pogleda obrazca." #. module: base #: model:res.country,name:base.ms @@ -3537,6 +3693,8 @@ msgid "" "The Selection Options expression is not a valid Pythonic expression.Please " "provide an expression in the [('key','Label'), ...] format." msgstr "" +"Izraz možnosti izražanja ni veljaven Pythonic izraza. Prosim navedite izraz " +"v [(\"ključ\", \"oznaka\"), ...] obliki." #. module: base #: model:ir.ui.menu,name:base.menu_translation_app @@ -3550,6 +3708,8 @@ msgid "" "The user's timezone, used to perform timezone conversions between the server " "and the client." msgstr "" +"Uporabniški časovni pas, uporabljen za pretvorbo časovnega pasa med " +"strežnikom in klientom." #. module: base #: field:ir.module.module,demo:0 @@ -3559,12 +3719,12 @@ msgstr "Predstavitveni podatki" #. module: base #: selection:base.language.install,lang:0 msgid "English (UK)" -msgstr "" +msgstr "Angleščina (Združeno kraljestvo)" #. module: base #: selection:base.language.install,lang:0 msgid "Japanese / 日本語" -msgstr "" +msgstr "Japonsko / 日本語" #. module: base #: help:workflow.transition,act_from:0 @@ -3572,11 +3732,13 @@ msgid "" "Source activity. When this activity is over, the condition is tested to " "determine if we can start the ACT_TO activity." msgstr "" +"Vir dejavnost. Ko je ta dejavnost končana je pogoj preizkušen, da se " +"ugotovi, ali bomo lahko začeli dejavnost ACT_TO." #. module: base #: model:res.partner.category,name:base.res_partner_category_3 msgid "Starter Partner" -msgstr "" +msgstr "Začetni partner" #. module: base #: help:ir.model.fields,relation_field:0 @@ -3584,6 +3746,8 @@ msgid "" "For one2many fields, the field on the target model that implement the " "opposite many2one relationship" msgstr "" +"Za one2many polja, v polje na ciljni model, ki izvajajo nasprotno odnos " +"many2one" #. module: base #: model:ir.model,name:base.model_ir_actions_act_window_view @@ -3598,12 +3762,12 @@ msgstr "Splet" #. module: base #: selection:base.language.install,lang:0 msgid "English (CA)" -msgstr "" +msgstr "Angleško (CA)" #. module: base #: model:ir.model,name:base.model_publisher_warranty_contract msgid "publisher_warranty.contract" -msgstr "" +msgstr "publisher_warranty.contract" #. module: base #: model:res.country,name:base.et @@ -3613,12 +3777,12 @@ msgstr "Etiopija" #. module: base #: help:res.country.state,code:0 msgid "The state code in three chars.\n" -msgstr "" +msgstr "Koda zvezne države v treh znakih.\n" #. module: base #: model:res.country,name:base.sj msgid "Svalbard and Jan Mayen Islands" -msgstr "" +msgstr "Svalbardovi in Jan Mayenovi otoki" #. module: base #: model:ir.model,name:base.model_ir_actions_wizard @@ -3639,17 +3803,17 @@ msgstr "Združi po" #: view:res.config:0 #: view:res.config.installer:0 msgid "title" -msgstr "" +msgstr "naslov" #. module: base #: model:ir.model,name:base.model_base_language_install msgid "Install Language" -msgstr "" +msgstr "Namesti jezik" #. module: base #: view:ir.translation:0 msgid "Translation" -msgstr "" +msgstr "Prevod" #. module: base #: selection:res.request,state:0 @@ -3669,34 +3833,34 @@ msgstr "Lastnost 'on_delete' za za 'many2one' polja" #. module: base #: field:ir.actions.server,write_id:0 msgid "Write Id" -msgstr "" +msgstr "Id zapisa" #. module: base #: model:ir.ui.menu,name:base.menu_product msgid "Products" -msgstr "" +msgstr "Izdelki" #. module: base #: field:ir.actions.act_window,domain:0 #: field:ir.filters,domain:0 msgid "Domain Value" -msgstr "" +msgstr "Vrednost domene" #. module: base #: view:ir.actions.server:0 msgid "SMS Configuration" -msgstr "" +msgstr "SMS konfiguracija" #. module: base #: selection:base.language.install,lang:0 msgid "Spanish (BO) / Español (BO)" -msgstr "" +msgstr "Špansko (BO) / Español (BO)" #. module: base #: model:ir.actions.act_window,name:base.ir_access_act #: model:ir.ui.menu,name:base.menu_ir_access_act msgid "Access Controls List" -msgstr "" +msgstr "Seznam kontrole dostopa" #. module: base #: model:res.country,name:base.um @@ -3707,7 +3871,7 @@ msgstr "" #: field:res.partner.bank,state:0 #: field:res.partner.bank.type.field,bank_type_id:0 msgid "Bank Type" -msgstr "" +msgstr "Vrsta banke" #. module: base #: code:addons/base/res/res_user.py:58 @@ -3738,11 +3902,13 @@ msgstr "" msgid "" "Unable to process module \"%s\" because an external dependency is not met: %s" msgstr "" +"Ni mogoče procesirati modula \"%s\", ker zunanja odvisnost ni izpolnjena: %s" #. module: base #: view:publisher_warranty.contract.wizard:0 msgid "Please enter the serial key provided in your contract document:" msgstr "" +"Prosim vnestite serijski ključ, ki je naveden na vašem dokumentu pogodbe" #. module: base #: view:workflow.activity:0 @@ -3754,23 +3920,23 @@ msgstr "Začetek poteka dela" #: code:addons/__init__.py:834 #, python-format msgid "module base cannot be loaded! (hint: verify addons-path)" -msgstr "" +msgstr "osnova modula ne more biti naložena (namig: preverite pod dodatkov)" #. module: base #: view:res.partner.bank:0 msgid "Bank Account Owner" -msgstr "" +msgstr "Lastnik bančnega računa" #. module: base #: model:ir.actions.act_window,name:base.act_values_form msgid "Client Actions Connections" -msgstr "" +msgstr "Povezave dejanj klienta" #. module: base #: field:ir.attachment,res_name:0 #: field:ir.ui.view_sc,resource:0 msgid "Resource Name" -msgstr "Naziv resursa" +msgstr "Ime vira" #. module: base #: selection:ir.cron,interval_type:0 @@ -3797,11 +3963,14 @@ msgid "" "form, signal tests the name of the pressed button. If signal is NULL, no " "button is necessary to validate this transition." msgstr "" +"Ko operacija transakcije pride iz pritisnjenega gumba v obrazcu klienta, " +"signal testira ime pritisnjenega gumba. Če je signal NULL, ni potreben gumb " +"za preverjanje transakcije." #. module: base #: help:multi_company.default,object_id:0 msgid "Object affected by this rule" -msgstr "" +msgstr "To pravilo vpliva na predmet" #. module: base #: report:ir.module.reference.graph:0 @@ -3811,17 +3980,17 @@ msgstr "Imenik" #. module: base #: field:wizard.ir.model.menu.create,name:0 msgid "Menu Name" -msgstr "Naziv menuja" +msgstr "Ime Menija" #. module: base #: view:ir.module.module:0 msgid "Author Website" -msgstr "" +msgstr "Avtorjeva spletna stran" #. module: base #: view:ir.attachment:0 msgid "Month" -msgstr "" +msgstr "Mesec" #. module: base #: model:res.country,name:base.my @@ -3832,7 +4001,7 @@ msgstr "Malezija" #: view:base.language.install:0 #: model:ir.actions.act_window,name:base.action_view_base_language_install msgid "Load Official Translation" -msgstr "" +msgstr "Naloži uraden prevod" #. module: base #: model:ir.model,name:base.model_res_request_history @@ -3842,7 +4011,7 @@ msgstr "res.request.history" #. module: base #: view:ir.actions.server:0 msgid "Client Action Configuration" -msgstr "" +msgstr "Nastavitve klientovih dejanj" #. module: base #: model:ir.model,name:base.model_res_partner_address @@ -3856,11 +4025,13 @@ msgid "" "Whether values for this field can be translated (enables the translation " "mechanism for that field)" msgstr "" +"Ali so lahko te vrednosti za to polje prevedene (omogoči prevajalni " +"mehanizem za to polje)" #. module: base #: view:res.lang:0 msgid "%S - Seconds [00,61]." -msgstr "" +msgstr "%S - Sekund [00,61]" #. module: base #: model:res.country,name:base.cv @@ -3870,7 +4041,7 @@ msgstr "Zelenortski otoki" #. module: base #: view:base.module.import:0 msgid "Select module package to import (.zip file):" -msgstr "" +msgstr "Izberite paket modula za uvoz (.zip datoteka)" #. module: base #: model:ir.actions.act_window,name:base.act_res_partner_event @@ -3889,13 +4060,14 @@ msgstr "ir.actions.url" #. module: base #: model:res.widget,title:base.currency_converter_widget msgid "Currency Converter" -msgstr "" +msgstr "Pretvornik valik" #. module: base #: code:addons/orm.py:156 #, python-format msgid "Wrong ID for the browse record, got %r, expected an integer." msgstr "" +"Napačen ID za brskanje zapisa, dobljen %r, pričakovano celo številko." #. module: base #: model:ir.actions.act_window,name:base.action_partner_addess_tree @@ -3911,7 +4083,7 @@ msgstr "Število dodanih modulov" #. module: base #: view:res.currency:0 msgid "Price Accuracy" -msgstr "" +msgstr "Natančnost cene" #. module: base #: selection:base.language.install,lang:0 @@ -3922,7 +4094,7 @@ msgstr "" #: view:res.config:0 #: view:res.config.installer:0 msgid "vsep" -msgstr "" +msgstr "vsep" #. module: base #: selection:base.language.install,lang:0 @@ -3933,17 +4105,17 @@ msgstr "" #: code:addons/orm.py:1049 #, python-format msgid "The create method is not implemented on this object !" -msgstr "Metoda 'create' ni implementirana za ta objekt." +msgstr "Metoda 'create' ni implementirana za ta predmet!" #. module: base #: field:workflow.triggers,workitem_id:0 msgid "Workitem" -msgstr "" +msgstr "Postavka dela" #. module: base #: view:ir.actions.todo:0 msgid "Set as Todo" -msgstr "" +msgstr "Nastavi na Je treba opraviti" #. module: base #: field:ir.actions.act_window.view,act_window_id:0 @@ -3954,7 +4126,7 @@ msgstr "" #: selection:ir.values,key:0 #: view:res.users:0 msgid "Action" -msgstr "Akcija" +msgstr "Dejanje" #. module: base #: view:ir.actions.server:0 @@ -3969,22 +4141,22 @@ msgstr "ir.cron" #. module: base #: view:ir.rule:0 msgid "Combination of rules" -msgstr "" +msgstr "Kombinacija pravil" #. module: base #: view:ir.sequence:0 msgid "Current Year without Century: %(y)s" -msgstr "" +msgstr "Trenutno leto brez stoletja: %(y)s" #. module: base #: field:ir.actions.server,trigger_obj_id:0 msgid "Trigger On" -msgstr "" +msgstr "Sprožilec vključen" #. module: base #: sql_constraint:ir.rule:0 msgid "Rule must have at least one checked access right !" -msgstr "" +msgstr "Pravilo mora imet vsaj eno označeno pravilo dostopa!" #. module: base #: model:res.country,name:base.fj @@ -4016,7 +4188,7 @@ msgstr "Zgodovina zahteve" #: field:ir.module.module,menus_by_module:0 #: view:res.groups:0 msgid "Menus" -msgstr "Menuji" +msgstr "Meniji" #. module: base #: selection:base.language.install,lang:0 @@ -4038,17 +4210,17 @@ msgstr "Ustvari dejanje" #: model:ir.model,name:base.model_ir_model #: model:ir.ui.menu,name:base.ir_model_model_menu msgid "Objects" -msgstr "Objekti" +msgstr "Predmeti" #. module: base #: field:res.lang,time_format:0 msgid "Time Format" -msgstr "Oblika zapisa časa" +msgstr "Oblika časa" #. module: base #: view:ir.module.module:0 msgid "Defined Reports" -msgstr "" +msgstr "Opredeljena poročila" #. module: base #: view:ir.actions.report.xml:0 @@ -4076,7 +4248,7 @@ msgstr "Delni potek" #. module: base #: model:ir.model,name:base.model_res_config msgid "res.config" -msgstr "" +msgstr "res.config" #. module: base #: field:workflow.transition,signal:0 @@ -4099,17 +4271,17 @@ msgstr "" #. module: base #: field:ir.cron,doall:0 msgid "Repeat Missed" -msgstr "" +msgstr "Zgrešene ponovitve" #. module: base #: help:ir.actions.server,state:0 msgid "Type of the Action that is to be executed" -msgstr "" +msgstr "Vrsta dejanja, ki bo izvršeno" #. module: base #: field:ir.server.object.lines,server_id:0 msgid "Object Mapping" -msgstr "Preslikava objekta" +msgstr "Preslikava predmeta" #. module: base #: help:res.currency,rate:0 @@ -4127,29 +4299,30 @@ msgstr "Združeno kraljestvo" #: view:res.config.users:0 #: view:res.config.view:0 msgid "res_config_contents" -msgstr "" +msgstr "res_config_contents" #. module: base #: help:res.partner.category,active:0 msgid "The active field allows you to hide the category without removing it." msgstr "" +"Polje dejanja vam dovoljuje skrivanje kategorije brez, da bi jo odstranili." #. module: base #: report:ir.module.reference.graph:0 msgid "Object:" -msgstr "Objekt:" +msgstr "Predmet:" #. module: base #: model:res.country,name:base.bw msgid "Botswana" -msgstr "" +msgstr "Botsvana" #. module: base #: model:ir.actions.act_window,name:base.action_partner_title_partner #: model:ir.ui.menu,name:base.menu_partner_title_partner #: view:res.partner.title:0 msgid "Partner Titles" -msgstr "" +msgstr "Nazivi partnerja" #. module: base #: help:ir.actions.act_window,auto_refresh:0 @@ -4159,7 +4332,7 @@ msgstr "Dodaj samoosvežitev k pogledu" #. module: base #: help:res.partner,employee:0 msgid "Check this box if the partner is an Employee." -msgstr "" +msgstr "Označi to polje, če je partner zaposlen" #. module: base #: field:ir.actions.report.xml,report_rml_content:0 @@ -4171,7 +4344,7 @@ msgstr "RML vsebina" #: model:ir.actions.act_window,name:base.action_workflow_workitem_form #: model:ir.ui.menu,name:base.menu_workflow_workitem msgid "Workitems" -msgstr "" +msgstr "Predmeti dela" #. module: base #: field:base.language.export,advice:0 @@ -4190,11 +4363,13 @@ msgid "" "You cannot perform this operation. New Record Creation is not allowed for " "this object as this object is for reporting purpose." msgstr "" +"Ne morete izvesti te operacije. Ustvaritev novega zapisa ni dovoljeno za ta " +"predemet, ker je ta predmet namenjen samo za poročanje." #. module: base #: view:base.language.import:0 msgid "- module,type,name,res_id,src,value" -msgstr "" +msgstr "- module,type,name,res_id,src,value" #. module: base #: selection:base.language.install,lang:0 @@ -4207,11 +4382,13 @@ msgid "" "Provide the field name where the record id is stored after the create " "operations. If it is empty, you can not track the new record." msgstr "" +"Navedite ime polja kjer je id zapisa shranjen po operaciji kreacije. Če je " +"prazen, ne morete slediti novega zapisa." #. module: base #: help:ir.model.fields,relation:0 msgid "For relationship fields, the technical name of the target model" -msgstr "" +msgstr "Za sorodna polja, tehnično ime ciljnega modela" #. module: base #: selection:base.language.install,lang:0 @@ -4226,43 +4403,43 @@ msgstr "Podedovan pogled" #. module: base #: view:ir.translation:0 msgid "Source Term" -msgstr "" +msgstr "Izraz izvora" #. module: base #: model:ir.ui.menu,name:base.menu_main_pm msgid "Project" -msgstr "" +msgstr "Projekt" #. module: base #: field:ir.ui.menu,web_icon_hover_data:0 msgid "Web Icon Image (hover)" -msgstr "" +msgstr "Slika spletne ikone (hover)" #. module: base #: view:base.module.import:0 msgid "Module file successfully imported!" -msgstr "" +msgstr "Datoteka modula je bila uspešno uvožena!" #. module: base #: selection:ir.actions.todo,state:0 msgid "Cancelled" -msgstr "" +msgstr "Preklicano" #. module: base #: view:res.config.users:0 msgid "Create User" -msgstr "" +msgstr "Ustvari uporabnika" #. module: base #: view:partner.clear.ids:0 msgid "Want to Clear Ids ? " -msgstr "" +msgstr "Želite počistiti Id-je? " #. module: base #: field:publisher_warranty.contract,name:0 #: field:publisher_warranty.contract.wizard,name:0 msgid "Serial Key" -msgstr "" +msgstr "Serijski ključ" #. module: base #: selection:res.request,priority:0 @@ -4272,12 +4449,12 @@ msgstr "Nizka" #. module: base #: model:ir.ui.menu,name:base.menu_audit msgid "Audit" -msgstr "" +msgstr "Pregled računov" #. module: base #: model:res.country,name:base.lc msgid "Saint Lucia" -msgstr "" +msgstr "Sveta Lucija" #. module: base #: view:publisher_warranty.contract:0 @@ -4287,12 +4464,12 @@ msgstr "Vzdrežvalna pogodba" #. module: base #: help:ir.actions.server,trigger_obj_id:0 msgid "Select the object from the model on which the workflow will executed." -msgstr "" +msgstr "Izberite predmet iz modela na katerem bo delovni proces izvršen." #. module: base #: field:res.partner,employee:0 msgid "Employee" -msgstr "" +msgstr "Zaposleni" #. module: base #: field:ir.model.access,perm_create:0 @@ -4302,34 +4479,34 @@ msgstr "Ustvari dostop" #. module: base #: field:res.partner.address,state_id:0 msgid "Fed. State" -msgstr "" +msgstr "Zvezna država" #. module: base #: field:ir.actions.server,copy_object:0 msgid "Copy Of" -msgstr "" +msgstr "Kopija" #. module: base #: field:ir.model,osv_memory:0 msgid "In-memory model" -msgstr "" +msgstr "Model v spominu" #. module: base #: view:partner.clear.ids:0 msgid "Clear Ids" -msgstr "" +msgstr "Počisti Id-je" #. module: base #: model:res.country,name:base.io msgid "British Indian Ocean Territory" -msgstr "Britanska ozemlja v Indijskem oceanu" +msgstr "Britansko ozemlje v indijskem oceanu" #. module: base #: field:res.config.users,view:0 #: field:res.config.view,view:0 #: field:res.users,view:0 msgid "Interface" -msgstr "" +msgstr "Vmesnik" #. module: base #: view:ir.actions.server:0 @@ -4339,7 +4516,7 @@ msgstr "Preslikava polj" #. module: base #: view:publisher_warranty.contract:0 msgid "Refresh Validation Dates" -msgstr "" +msgstr "Osveži datume preverjanja" #. module: base #: view:ir.model:0 @@ -4395,7 +4572,7 @@ msgstr "Ni implementirano" #. module: base #: model:ir.model,name:base.model_res_widget_user msgid "res.widget.user" -msgstr "" +msgstr "res.widget.user" #. module: base #: field:res.partner.category,complete_name:0 @@ -4405,18 +4582,18 @@ msgstr "Polno ime" #. module: base #: view:base.module.configuration:0 msgid "_Ok" -msgstr "" +msgstr "_V redu" #. module: base #: help:ir.filters,user_id:0 msgid "False means for every user" -msgstr "" +msgstr "False pomeni za vsakega uporabnika" #. module: base #: code:addons/base/module/module.py:198 #, python-format msgid "The name of the module must be unique !" -msgstr "" +msgstr "Ime modula mora biti edinstven!" #. module: base #: model:res.country,name:base.mz @@ -4426,7 +4603,7 @@ msgstr "Mozambik" #. module: base #: model:ir.ui.menu,name:base.menu_project_long_term msgid "Long Term Planning" -msgstr "" +msgstr "Dolgoročno načrtovanje" #. module: base #: field:ir.actions.server,message:0 @@ -4439,13 +4616,13 @@ msgstr "Sporočilo" #. module: base #: field:ir.actions.act_window.view,multi:0 msgid "On Multiple Doc." -msgstr "" +msgstr "Na večih dokumentih" #. module: base #: view:res.partner:0 #: field:res.partner,user_id:0 msgid "Salesman" -msgstr "" +msgstr "Prodajalec" #. module: base #: field:res.partner,address:0 @@ -4459,11 +4636,12 @@ msgstr "Stiki" msgid "" "Unable to delete this document because it is used as a default property" msgstr "" +"Ne morem izbrisati tega dokumenta, ker se uporablja kot privzeta lastnost" #. module: base #: view:res.widget.wizard:0 msgid "Add" -msgstr "" +msgstr "Dodaj" #. module: base #: view:base.module.upgrade:0 @@ -4475,7 +4653,7 @@ msgstr "Izvedi planirane nadgradnje" #. module: base #: view:res.widget:0 msgid "Widgets" -msgstr "" +msgstr "Gradniki" #. module: base #: model:res.country,name:base.cz @@ -4485,7 +4663,7 @@ msgstr "Češka republika" #. module: base #: view:res.widget.wizard:0 msgid "Widget Wizard" -msgstr "" +msgstr "Čarovnik gradnikov" #. module: base #: model:ir.actions.act_window,help:base.act_ir_actions_todo_form @@ -4494,6 +4672,9 @@ msgid "" "OpenERP. They are launched during the installation of new modules, but you " "can choose to restart some wizards manually from this menu." msgstr "" +"Konfiguracijski čarovniki se uporabljajo za konfiguracijo novega primerka " +"OpenERP. Ti se zaženejo med namestitvijo novih modulov, vendar pa se lahko " +"odločite, da ponovno zaženete nekaj čarovnikov ročno iz tega menija." #. module: base #: code:addons/base/res/res_user.py:206 @@ -4502,17 +4683,19 @@ msgid "" "Please use the change password wizard (in User Preferences or User menu) to " "change your own password." msgstr "" +"Prosim, uporabite ta čarovnik za spreminjanje glesa (v Uporabniških " +"nastavitvah ali meniju Uporabnik), za spremembo vašega gesla." #. module: base #: code:addons/orm.py:1350 #, python-format msgid "Insufficient fields for Calendar View!" -msgstr "" +msgstr "Premalo pol za pogled koledarja!" #. module: base #: selection:ir.property,type:0 msgid "Integer" -msgstr "" +msgstr "Celo število" #. module: base #: help:ir.actions.report.xml,report_rml:0 @@ -4520,12 +4703,14 @@ msgid "" "The path to the main report file (depending on Report Type) or NULL if the " "content is in another data field" msgstr "" +"Pot do datoteke glavnega poročila (odvisno od vrste poročila) ali NULL, če " +"je vsebina v drugem polju podatkov" #. module: base #: help:res.config.users,company_id:0 #: help:res.users,company_id:0 msgid "The company this user is currently working for." -msgstr "" +msgstr "Podjetje, za katerega trenutno dela ta uporabnik." #. module: base #: model:ir.model,name:base.model_wizard_ir_model_menu_create @@ -4540,7 +4725,7 @@ msgstr "Prehod" #. module: base #: field:res.groups,menu_access:0 msgid "Access Menu" -msgstr "" +msgstr "Meni dostopa" #. module: base #: model:res.country,name:base.na @@ -4555,12 +4740,12 @@ msgstr "Mongolija" #. module: base #: view:ir.module.module:0 msgid "Created Menus" -msgstr "" +msgstr "Ustvarjeni meniji" #. module: base #: selection:ir.ui.view,type:0 msgid "mdx" -msgstr "" +msgstr "mdx" #. module: base #: model:res.country,name:base.bi @@ -4581,12 +4766,12 @@ msgstr "Zapri" #. module: base #: selection:base.language.install,lang:0 msgid "Spanish (MX) / Español (MX)" -msgstr "" +msgstr "Špansko (MX) / Español (MX)" #. module: base #: view:res.log:0 msgid "My Logs" -msgstr "" +msgstr "Moji dnevniki" #. module: base #: model:res.country,name:base.bt @@ -4596,7 +4781,7 @@ msgstr "Butan" #. module: base #: help:ir.sequence,number_next:0 msgid "Next number of this sequence" -msgstr "" +msgstr "Naslednja številka tega zaporedja" #. module: base #: model:res.partner.category,name:base.res_partner_category_11 @@ -4611,12 +4796,12 @@ msgstr "To okno" #. module: base #: view:publisher_warranty.contract:0 msgid "Publisher Warranty Contracts" -msgstr "" +msgstr "Pogodbe založniške garancije" #. module: base #: help:res.log,name:0 msgid "The logging message." -msgstr "" +msgstr "Prijavno sporočilo." #. module: base #: field:base.language.export,format:0 @@ -4626,7 +4811,7 @@ msgstr "Oblika datoteke" #. module: base #: field:res.lang,iso_code:0 msgid "ISO code" -msgstr "" +msgstr "ISO koda" #. module: base #: model:ir.model,name:base.model_res_config_view @@ -4637,12 +4822,12 @@ msgstr "res.config.view" #: view:res.log:0 #: field:res.log,read:0 msgid "Read" -msgstr "" +msgstr "Branje" #. module: base #: sql_constraint:res.country:0 msgid "The name of the country must be unique !" -msgstr "" +msgstr "Ime države mora biti edinstveno!" #. module: base #: model:ir.actions.act_window,help:base.action_country_state @@ -4651,11 +4836,13 @@ msgid "" "federal states you are working on from here. Each state is attached to one " "country." msgstr "" +"Če delate na ameriškem trgu, lahko tukaj upravljate različne zvezne dežele " +"na katerih delatej. Vsako stanje je vezano na eno državo." #. module: base #: view:workflow.workitem:0 msgid "Workflow Workitems" -msgstr "Elementi poteka dela" +msgstr "Elementi delovnih procesov" #. module: base #: model:res.country,name:base.vc @@ -4682,13 +4869,13 @@ msgstr "Polja" #. module: base #: model:ir.actions.act_window,name:base.action_partner_employee_form msgid "Employees" -msgstr "" +msgstr "Zaposleni" #. module: base #: help:res.log,read:0 msgid "" "If this log item has been read, get() should not send it to the client" -msgstr "" +msgstr "Če je bil ta predmet dnevnika prebran, get() ne sme poslati klientu" #. module: base #: field:res.company,rml_header2:0 @@ -4713,6 +4900,10 @@ msgid "" "channels that will be maintained at the creation of a document in the " "system. Some examples of channels can be: Website, Phone Call, Reseller, etc." msgstr "" +"Sledite od kje prihajajo vaše poti in priložnosti z ustvarjanjem " +"specifičnega kanala, ki se bo vzdrževal z ustvarjanjem dokumenta v sistemu. " +"Nekateri primeri kanalov so lahko: Spletna stran, Telefonski klic, " +"Preprodajalec, itd." #. module: base #: model:res.partner.bank.type.field,name:base.bank_normal_field @@ -4791,7 +4982,7 @@ msgstr "Burkina Faso" #. module: base #: selection:ir.actions.todo,state:0 msgid "Skipped" -msgstr "Preskočeno" +msgstr "Izpuščeno" #. module: base #: selection:ir.model.fields,state:0 @@ -4801,7 +4992,7 @@ msgstr "Polje po meri" #. module: base #: field:ir.module.module,web:0 msgid "Has a web component" -msgstr "" +msgstr "Ima spletno komponento" #. module: base #: model:res.country,name:base.cc @@ -4813,17 +5004,17 @@ msgstr "Kokosovi (Keelingovi) otoki" #: selection:base.module.import,state:0 #: selection:base.module.update,state:0 msgid "init" -msgstr "" +msgstr "init" #. module: base #: view:res.lang:0 msgid "11. %U or %W ==> 48 (49th week)" -msgstr "" +msgstr "11. %U ali %w ==> 48 (49 teden)" #. module: base #: model:ir.model,name:base.model_res_partner_bank_type_field msgid "Bank type fields" -msgstr "" +msgstr "Polja vrste banke" #. module: base #: selection:base.language.install,lang:0 @@ -4838,11 +5029,14 @@ msgid "" "\n" "This addon is already installed on your system" msgstr "" +"\n" +"\n" +"Ta dodatek je že nameščen na vaš sistem" #. module: base #: help:ir.cron,interval_number:0 msgid "Repeat every x." -msgstr "" +msgstr "Ponovi vsakih x." #. module: base #: wizard_view:server.action.create,step_1:0 @@ -4858,7 +5052,7 @@ msgstr "1cm 28cm 20cm 28cm" #. module: base #: field:ir.module.module,maintainer:0 msgid "Maintainer" -msgstr "" +msgstr "Vzdrževalec" #. module: base #: field:ir.sequence,suffix:0 @@ -4883,17 +5077,17 @@ msgstr "E-pošta pošiljatelja" #. module: base #: field:ir.default,field_name:0 msgid "Object Field" -msgstr "" +msgstr "Polje predmeta" #. module: base #: selection:base.language.install,lang:0 msgid "Spanish (PE) / Español (PE)" -msgstr "" +msgstr "Špansko (PE) / Español (PE)" #. module: base #: selection:base.language.install,lang:0 msgid "French (CH) / Français (CH)" -msgstr "" +msgstr "Francosko (CH) / Français (CH)" #. module: base #: help:res.config.users,action_id:0 @@ -4902,17 +5096,19 @@ msgid "" "If specified, this action will be opened at logon for this user, in addition " "to the standard menu." msgstr "" +"Če je navedeno, bo to dejanje odprto ob prijavi tega uporabnika, poleg " +"standardnega menija." #. module: base #: view:ir.values:0 msgid "Client Actions" -msgstr "" +msgstr "Klientova dejanja" #. module: base #: code:addons/orm.py:1806 #, python-format msgid "The exists method is not implemented on this object !" -msgstr "" +msgstr "Obstoječa metoda ni implementirana v ta predmet!" #. module: base #: code:addons/base/module/module.py:336 @@ -4921,21 +5117,23 @@ msgid "" "You try to upgrade a module that depends on the module: %s.\n" "But this module is not available in your system." msgstr "" +"Poizkušate nadgraditi modul, ki je odvisen od tega modula: %s.\n" +"Ampak ta modul ni dostopen na vašem sistemu." #. module: base #: field:workflow.transition,act_to:0 msgid "Destination Activity" -msgstr "" +msgstr "Dejanja destinacije" #. module: base #: view:ir.values:0 msgid "Connect Events to Actions" -msgstr "" +msgstr "Poveži dogodke dejanjem" #. module: base #: model:ir.model,name:base.model_base_update_translations msgid "base.update.translations" -msgstr "" +msgstr "base.update.translations" #. module: base #: field:ir.module.category,parent_id:0 @@ -4975,12 +5173,12 @@ msgstr "Prekliči odstranitev" #: view:res.partner:0 #: view:res.partner.address:0 msgid "Communication" -msgstr "" +msgstr "Komunikacija" #. module: base #: view:ir.actions.report.xml:0 msgid "RML Report" -msgstr "" +msgstr "RML poročilo" #. module: base #: model:ir.model,name:base.model_ir_server_object_lines @@ -4991,7 +5189,7 @@ msgstr "ir.server.object.lines" #: code:addons/base/module/module.py:531 #, python-format msgid "Module %s: Invalid Quality Certificate" -msgstr "" +msgstr "Modul %s: Neveljavno potrdilo kakovosti" #. module: base #: model:res.country,name:base.kw @@ -5001,7 +5199,7 @@ msgstr "Kuvajt" #. module: base #: field:workflow.workitem,inst_id:0 msgid "Instance" -msgstr "Primerek" +msgstr "Primer" #. module: base #: help:ir.actions.report.xml,attachment:0 @@ -5010,11 +5208,14 @@ msgid "" "Keep empty to not save the printed reports. You can use a python expression " "with the object and time variables." msgstr "" +"To je ime datoteke priloge, ki se uporablja za shranjevanje tiskanja " +"rezultatov. Naj bo prazno, če ne želite shraniti tiskanih poročil. Lahko " +"uporabite python izraz s predmetom in spremenljivk časa." #. module: base #: selection:ir.property,type:0 msgid "Many2One" -msgstr "" +msgstr "Many2One" #. module: base #: model:res.country,name:base.ng @@ -6657,7 +6858,7 @@ msgstr "Naslednji konfiguracijski korak" #. module: base #: field:res.groups,comment:0 msgid "Comment" -msgstr "Pripomba" +msgstr "Opomba" #. module: base #: model:res.country,name:base.ro diff --git a/openerp/addons/base/i18n/zh_HK.po b/openerp/addons/base/i18n/zh_HK.po new file mode 100644 index 00000000000..75dd21f04ff --- /dev/null +++ b/openerp/addons/base/i18n/zh_HK.po @@ -0,0 +1,9248 @@ +# Chinese (Hong Kong) translation for openobject-server +# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011 +# This file is distributed under the same license as the openobject-server package. +# FIRST AUTHOR , 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-server\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2011-01-11 11:14+0000\n" +"PO-Revision-Date: 2011-09-27 16:39+0000\n" +"Last-Translator: Walter Cheuk \n" +"Language-Team: Chinese (Hong Kong) \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2011-09-28 05:19+0000\n" +"X-Generator: Launchpad (build 14049)\n" + +#. module: base +#: view:ir.filters:0 +#: field:ir.model.fields,domain:0 +#: field:ir.rule,domain:0 +#: field:ir.rule,domain_force:0 +#: field:res.partner.title,domain:0 +msgid "Domain" +msgstr "" + +#. module: base +#: model:res.country,name:base.sh +msgid "Saint Helena" +msgstr "" + +#. module: base +#: view:ir.actions.report.xml:0 +msgid "Other Configuration" +msgstr "" + +#. module: base +#: selection:ir.property,type:0 +msgid "DateTime" +msgstr "" + +#. module: base +#: code:addons/fields.py:534 +#, python-format +msgid "" +"The second argument of the many2many field %s must be a SQL table !You used " +"%s, which is not a valid SQL table name." +msgstr "" + +#. module: base +#: view:ir.values:0 +#: field:ir.values,meta_unpickle:0 +msgid "Metadata" +msgstr "" + +#. module: base +#: field:ir.ui.view,arch:0 +#: field:ir.ui.view.custom,arch:0 +msgid "View Architecture" +msgstr "" + +#. module: base +#: field:base.language.import,code:0 +msgid "Code (eg:en__US)" +msgstr "" + +#. module: base +#: view:workflow:0 +#: view:workflow.activity:0 +#: field:workflow.activity,wkf_id:0 +#: field:workflow.instance,wkf_id:0 +#: field:workflow.transition,wkf_id:0 +#: field:workflow.workitem,wkf_id:0 +msgid "Workflow" +msgstr "" + +#. module: base +#: view:partner.sms.send:0 +msgid "SMS - Gateway: clickatell" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Hungarian / Magyar" +msgstr "" + +#. module: base +#: selection:ir.model.fields,select_level:0 +msgid "Not Searchable" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Spanish (VE) / Español (VE)" +msgstr "" + +#. module: base +#: field:ir.actions.server,wkf_model_id:0 +msgid "Workflow On" +msgstr "" + +#. module: base +#: field:ir.actions.act_window,display_menu_tip:0 +msgid "Display Menu Tips" +msgstr "" + +#. module: base +#: view:ir.module.module:0 +msgid "Created Views" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_model.py:485 +#, python-format +msgid "" +"You can not write in this document (%s) ! Be sure your user belongs to one " +"of these groups: %s." +msgstr "" + +#. module: base +#: help:ir.model.fields,domain:0 +msgid "" +"The optional domain to restrict possible values for relationship fields, " +"specified as a Python expression defining a list of triplets. For example: " +"[('color','=','red')]" +msgstr "" + +#. module: base +#: field:res.partner,ref:0 +msgid "Reference" +msgstr "" + +#. module: base +#: field:ir.actions.act_window,target:0 +msgid "Target Window" +msgstr "" + +#. module: base +#: code:addons/base/res/res_user.py:507 +#, python-format +msgid "Warning!" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_model.py:304 +#, python-format +msgid "" +"Properties of base fields cannot be altered in this manner! Please modify " +"them through Python code, preferably through a custom addon!" +msgstr "" + +#. module: base +#: code:addons/osv.py:133 +#, python-format +msgid "Constraint Error" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_ui_view_custom +msgid "ir.ui.view.custom" +msgstr "" + +#. module: base +#: model:res.country,name:base.sz +msgid "Swaziland" +msgstr "" + +#. module: base +#: code:addons/orm.py:1993 +#: code:addons/orm.py:3653 +#, python-format +msgid "created." +msgstr "" + +#. module: base +#: model:res.partner.category,name:base.res_partner_category_woodsuppliers0 +msgid "Wood Suppliers" +msgstr "" + +#. module: base +#: code:addons/base/module/module.py:303 +#, python-format +msgid "" +"Some installed modules depend on the module you plan to Uninstall :\n" +" %s" +msgstr "" + +#. module: base +#: field:ir.sequence,number_increment:0 +msgid "Increment Number" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_res_company_tree +#: model:ir.ui.menu,name:base.menu_action_res_company_tree +msgid "Company's Structure" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Inuktitut / ᐃᓄᒃᑎᑐᑦ" +msgstr "" + +#. module: base +#: view:res.partner:0 +msgid "Search Partner" +msgstr "" + +#. module: base +#: code:addons/base/res/res_user.py:132 +#, python-format +msgid "\"smtp_server\" needs to be set to send mails to users" +msgstr "" + +#. module: base +#: code:addons/base/module/wizard/base_export_language.py:60 +#, python-format +msgid "new" +msgstr "" + +#. module: base +#: field:ir.actions.report.xml,multi:0 +msgid "On multiple doc." +msgstr "" + +#. module: base +#: field:ir.module.category,module_nr:0 +msgid "Number of Modules" +msgstr "" + +#. module: base +#: help:multi_company.default,company_dest_id:0 +msgid "Company to store the current record" +msgstr "" + +#. module: base +#: field:res.partner.bank.type.field,size:0 +msgid "Max. Size" +msgstr "" + +#. module: base +#: field:res.partner.address,name:0 +msgid "Contact Name" +msgstr "" + +#. module: base +#: code:addons/base/module/wizard/base_export_language.py:56 +#, python-format +msgid "" +"Save this document to a %s file and edit it with a specific software or a " +"text editor. The file encoding is UTF-8." +msgstr "" + +#. module: base +#: sql_constraint:res.lang:0 +msgid "The name of the language must be unique !" +msgstr "" + +#. module: base +#: selection:res.request,state:0 +msgid "active" +msgstr "" + +#. module: base +#: field:ir.actions.wizard,wiz_name:0 +msgid "Wizard Name" +msgstr "" + +#. module: base +#: code:addons/orm.py:2160 +#, python-format +msgid "Invalid group_by" +msgstr "" + +#. module: base +#: field:res.partner,credit_limit:0 +msgid "Credit Limit" +msgstr "" + +#. module: base +#: field:ir.model.data,date_update:0 +msgid "Update Date" +msgstr "" + +#. module: base +#: view:ir.attachment:0 +msgid "Owner" +msgstr "" + +#. module: base +#: field:ir.actions.act_window,src_model:0 +msgid "Source Object" +msgstr "" + +#. module: base +#: view:ir.actions.todo:0 +msgid "Config Wizard Steps" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_ui_view_sc +msgid "ir.ui.view_sc" +msgstr "" + +#. module: base +#: field:res.widget.user,widget_id:0 +#: field:res.widget.wizard,widgets_list:0 +msgid "Widget" +msgstr "" + +#. module: base +#: view:ir.model.access:0 +#: field:ir.model.access,group_id:0 +#: view:res.config.users:0 +msgid "Group" +msgstr "" + +#. module: base +#: field:ir.exports.line,name:0 +#: field:ir.translation,name:0 +#: field:res.partner.bank.type.field,name:0 +msgid "Field Name" +msgstr "" + +#. module: base +#: wizard_view:server.action.create,init:0 +#: wizard_field:server.action.create,init,type:0 +msgid "Select Action Type" +msgstr "" + +#. module: base +#: model:res.country,name:base.tv +msgid "Tuvalu" +msgstr "" + +#. module: base +#: selection:ir.model,state:0 +msgid "Custom Object" +msgstr "" + +#. module: base +#: field:res.lang,date_format:0 +msgid "Date Format" +msgstr "" + +#. module: base +#: field:res.bank,email:0 +#: field:res.partner.address,email:0 +msgid "E-Mail" +msgstr "" + +#. module: base +#: model:res.country,name:base.an +msgid "Netherlands Antilles" +msgstr "" + +#. module: base +#: code:addons/base/res/res_user.py:389 +#, python-format +msgid "" +"You can not remove the admin user as it is used internally for resources " +"created by OpenERP (updates, module installation, ...)" +msgstr "" + +#. module: base +#: model:res.country,name:base.gf +msgid "French Guyana" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Greek / Ελληνικά" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Bosnian / bosanski jezik" +msgstr "" + +#. module: base +#: help:ir.actions.report.xml,attachment_use:0 +msgid "" +"If you check this, then the second time the user prints with same attachment " +"name, it returns the previous report." +msgstr "" + +#. module: base +#: code:addons/orm.py:904 +#, python-format +msgid "The read method is not implemented on this object !" +msgstr "" + +#. module: base +#: help:res.lang,iso_code:0 +msgid "This ISO code is the name of po files to use for translations" +msgstr "" + +#. module: base +#: view:base.module.upgrade:0 +msgid "Your system will be updated." +msgstr "" + +#. module: base +#: field:ir.actions.todo,note:0 +#: selection:ir.property,type:0 +msgid "Text" +msgstr "" + +#. module: base +#: field:res.country,name:0 +msgid "Country Name" +msgstr "" + +#. module: base +#: model:res.country,name:base.co +msgid "Colombia" +msgstr "" + +#. module: base +#: view:ir.module.module:0 +msgid "Schedule Upgrade" +msgstr "" + +#. module: base +#: code:addons/orm.py:838 +#, python-format +msgid "Key/value '%s' not found in selection field '%s'" +msgstr "" + +#. module: base +#: help:res.country,code:0 +msgid "" +"The ISO country code in two chars.\n" +"You can use this field for quick search." +msgstr "" + +#. module: base +#: model:res.country,name:base.pw +msgid "Palau" +msgstr "" + +#. module: base +#: view:res.partner:0 +msgid "Sales & Purchases" +msgstr "" + +#. module: base +#: view:ir.translation:0 +msgid "Untranslated" +msgstr "" + +#. module: base +#: help:ir.actions.act_window,context:0 +msgid "" +"Context dictionary as Python expression, empty by default (Default: {})" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.ir_action_wizard +#: view:ir.actions.wizard:0 +#: model:ir.ui.menu,name:base.menu_ir_action_wizard +msgid "Wizards" +msgstr "" + +#. module: base +#: model:res.partner.category,name:base.res_partner_category_miscellaneoussuppliers0 +msgid "Miscellaneous Suppliers" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_model.py:255 +#, python-format +msgid "Custom fields must have a name that starts with 'x_' !" +msgstr "" + +#. module: base +#: help:ir.actions.server,action_id:0 +msgid "Select the Action Window, Report, Wizard to be executed." +msgstr "" + +#. module: base +#: view:res.config.users:0 +msgid "New User" +msgstr "" + +#. module: base +#: view:base.language.export:0 +msgid "Export done" +msgstr "" + +#. module: base +#: view:ir.model:0 +msgid "Model Description" +msgstr "" + +#. module: base +#: help:ir.actions.act_window,src_model:0 +msgid "" +"Optional model name of the objects on which this action should be visible" +msgstr "" + +#. module: base +#: field:workflow.transition,trigger_expr_id:0 +msgid "Trigger Expression" +msgstr "" + +#. module: base +#: model:res.country,name:base.jo +msgid "Jordan" +msgstr "" + +#. module: base +#: view:ir.module.module:0 +msgid "Certified" +msgstr "" + +#. module: base +#: model:res.country,name:base.er +msgid "Eritrea" +msgstr "" + +#. module: base +#: view:res.config:0 +#: view:res.config.installer:0 +msgid "description" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_base_action_rule +msgid "Automated Actions" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_actions_actions +msgid "ir.actions.actions" +msgstr "" + +#. module: base +#: view:partner.wizard.ean.check:0 +msgid "Want to check Ean ? " +msgstr "" + +#. module: base +#: field:ir.values,key2:0 +msgid "Event Type" +msgstr "" + +#. module: base +#: view:base.language.export:0 +msgid "" +"OpenERP translations (core, modules, clients) are managed through " +"Launchpad.net, our open source project management facility. We use their " +"online interface to synchronize all translations efforts." +msgstr "" + +#. module: base +#: field:res.partner,title:0 +msgid "Partner Form" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Swedish / svenska" +msgstr "" + +#. module: base +#: model:res.country,name:base.rs +msgid "Serbia" +msgstr "" + +#. module: base +#: selection:ir.translation,type:0 +msgid "Wizard View" +msgstr "" + +#. module: base +#: model:res.country,name:base.kh +msgid "Cambodia, Kingdom of" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.ir_sequence_form +#: view:ir.sequence:0 +#: model:ir.ui.menu,name:base.menu_ir_sequence_form +#: model:ir.ui.menu,name:base.next_id_5 +msgid "Sequences" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_base_language_import +msgid "Language Import" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_config_users +msgid "res.config.users" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Albanian / Shqip" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_crm_config_opportunity +msgid "Opportunities" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_base_language_export +msgid "base.language.export" +msgstr "" + +#. module: base +#: model:res.country,name:base.pg +msgid "Papua New Guinea" +msgstr "" + +#. module: base +#: help:ir.actions.report.xml,report_type:0 +msgid "Report Type, e.g. pdf, html, raw, sxw, odt, html2html, mako2html, ..." +msgstr "" + +#. module: base +#: model:res.partner.category,name:base.res_partner_category_4 +msgid "Basic Partner" +msgstr "" + +#. module: base +#: report:ir.module.reference.graph:0 +msgid "," +msgstr "" + +#. module: base +#: view:res.partner:0 +msgid "My Partners" +msgstr "" + +#. module: base +#: view:ir.actions.report.xml:0 +msgid "XML Report" +msgstr "" + +#. module: base +#: model:res.country,name:base.es +msgid "Spain" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_translation_export +msgid "Import / Export" +msgstr "" + +#. module: base +#: help:ir.actions.act_window,domain:0 +msgid "" +"Optional domain filtering of the destination data, as a Python expression" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_view_base_module_upgrade +#: model:ir.model,name:base.model_base_module_upgrade +msgid "Module Upgrade" +msgstr "" + +#. module: base +#: view:res.config.users:0 +msgid "" +"Groups are used to define access rights on objects and the visibility of " +"screens and menus" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Spanish (UY) / Español (UY)" +msgstr "" + +#. module: base +#: field:res.partner,mobile:0 +#: field:res.partner.address,mobile:0 +msgid "Mobile" +msgstr "" + +#. module: base +#: model:res.country,name:base.om +msgid "Oman" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_payterm_form +#: model:ir.model,name:base.model_res_payterm +msgid "Payment term" +msgstr "" + +#. module: base +#: model:res.country,name:base.nu +msgid "Niue" +msgstr "" + +#. module: base +#: selection:ir.cron,interval_type:0 +msgid "Work Days" +msgstr "" + +#. module: base +#: selection:ir.module.module,license:0 +msgid "Other OSI Approved Licence" +msgstr "" + +#. module: base +#: help:res.config.users,context_lang:0 +#: help:res.users,context_lang:0 +msgid "" +"Sets the language for the user's user interface, when UI translations are " +"available" +msgstr "" + +#. module: base +#: code:addons/orm.py:1043 +#, python-format +msgid "The unlink method is not implemented on this object !" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.act_menu_create +#: view:wizard.ir.model.menu.create:0 +msgid "Create Menu" +msgstr "" + +#. module: base +#: model:res.country,name:base.in +msgid "India" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.res_request_link-act +#: model:ir.ui.menu,name:base.menu_res_request_link_act +msgid "Request Reference Types" +msgstr "" + +#. module: base +#: view:ir.values:0 +msgid "client_action_multi, client_action_relate" +msgstr "" + +#. module: base +#: model:res.country,name:base.ad +msgid "Andorra, Principality of" +msgstr "" + +#. module: base +#: field:ir.module.category,child_ids:0 +#: field:res.partner.category,child_ids:0 +msgid "Child Categories" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_config_parameter +msgid "ir.config_parameter" +msgstr "" + +#. module: base +#: selection:base.language.export,format:0 +msgid "TGZ Archive" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "%B - Full month name." +msgstr "" + +#. module: base +#: view:ir.attachment:0 +#: field:ir.attachment,type:0 +#: field:ir.model,state:0 +#: field:ir.model.fields,state:0 +#: field:ir.property,type:0 +#: field:ir.server.object.lines,type:0 +#: field:ir.translation,type:0 +#: view:ir.ui.view:0 +#: view:ir.values:0 +#: field:ir.values,key:0 +#: view:res.partner:0 +#: view:res.partner.address:0 +msgid "Type" +msgstr "類型" + +#. module: base +#: code:addons/orm.py:210 +#, python-format +msgid "" +"Language with code \"%s\" is not defined in your system !\n" +"Define it through the Administration menu." +msgstr "" + +#. module: base +#: model:res.country,name:base.gu +msgid "Guam (USA)" +msgstr "關島(美屬)" + +#. module: base +#: model:ir.ui.menu,name:base.menu_hr_project +msgid "Human Resources Dashboard" +msgstr "" + +#. module: base +#: code:addons/base/res/res_user.py:507 +#, python-format +msgid "Setting empty passwords is not allowed for security reasons!" +msgstr "因保安理由密碼不能留空!" + +#. module: base +#: selection:ir.actions.server,state:0 +#: selection:workflow.activity,kind:0 +msgid "Dummy" +msgstr "" + +#. module: base +#: constraint:ir.ui.view:0 +msgid "Invalid XML for View Architecture!" +msgstr "" + +#. module: base +#: model:res.country,name:base.ky +msgid "Cayman Islands" +msgstr "開曼羣島" + +#. module: base +#: model:res.country,name:base.kr +msgid "South Korea" +msgstr "南韓" + +#. module: base +#: model:ir.actions.act_window,name:base.action_workflow_transition_form +#: model:ir.ui.menu,name:base.menu_workflow_transition +#: view:workflow.activity:0 +msgid "Transitions" +msgstr "" + +#. module: base +#: code:addons/orm.py:4020 +#, python-format +msgid "Record #%d of %s not found, cannot copy!" +msgstr "" + +#. module: base +#: field:ir.module.module,contributors:0 +msgid "Contributors" +msgstr "" + +#. module: base +#: selection:ir.property,type:0 +msgid "Char" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_publisher_warranty_contract_form +#: model:ir.ui.menu,name:base.menu_publisher_warranty_contract +msgid "Contracts" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Spanish (AR) / Español (AR)" +msgstr "西班牙文 (AR) / Español (AR)" + +#. module: base +#: model:res.country,name:base.ug +msgid "Uganda" +msgstr "烏干達" + +#. module: base +#: field:ir.model.access,perm_unlink:0 +msgid "Delete Access" +msgstr "" + +#. module: base +#: model:res.country,name:base.ne +msgid "Niger" +msgstr "尼日爾" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Chinese (HK)" +msgstr "中文(香港)" + +#. module: base +#: model:res.country,name:base.ba +msgid "Bosnia-Herzegovina" +msgstr "波斯尼亞" + +#. module: base +#: view:base.language.export:0 +msgid "" +"To improve or expand the official translations, you should use directly " +"Lauchpad's web interface (Rosetta). If you need to perform mass translation, " +"Launchpad also allows uploading full .po files at once" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Spanish (GT) / Español (GT)" +msgstr "西班牙文 (GT) / Español (GT)" + +#. module: base +#: view:res.lang:0 +msgid "" +"%W - Week number of the year (Monday as the first day of the week) as a " +"decimal number [00,53]. All days in a new year preceding the first Monday " +"are considered to be in week 0." +msgstr "" + +#. module: base +#: field:ir.module.module,website:0 +#: field:res.partner,website:0 +msgid "Website" +msgstr "網站" + +#. module: base +#: model:res.country,name:base.gs +msgid "S. Georgia & S. Sandwich Isls." +msgstr "南喬治亞和南三文治羣島" + +#. module: base +#: field:ir.actions.url,url:0 +msgid "Action URL" +msgstr "" + +#. module: base +#: field:base.module.import,module_name:0 +msgid "Module Name" +msgstr "" + +#. module: base +#: model:res.country,name:base.mh +msgid "Marshall Islands" +msgstr "馬紹爾羣島" + +#. module: base +#: code:addons/base/ir/ir_model.py:328 +#, python-format +msgid "Changing the model of a field is forbidden!" +msgstr "" + +#. module: base +#: model:res.country,name:base.ht +msgid "Haiti" +msgstr "海地" + +#. module: base +#: view:ir.ui.view:0 +#: selection:ir.ui.view,type:0 +msgid "Search" +msgstr "搜尋" + +#. module: base +#: code:addons/osv.py:136 +#, python-format +msgid "" +"The operation cannot be completed, probably due to the following:\n" +"- deletion: you may be trying to delete a record while other records still " +"reference it\n" +"- creation/update: a mandatory field is not correctly set" +msgstr "" + +#. module: base +#: view:ir.rule:0 +msgid "" +"2. Group-specific rules are combined together with a logical AND operator" +msgstr "" + +#. module: base +#: code:addons/base/res/res_user.py:206 +#, python-format +msgid "Operation Canceled" +msgstr "" + +#. module: base +#: help:base.language.export,lang:0 +msgid "To export a new language, do not select a language." +msgstr "" + +#. module: base +#: view:res.request:0 +msgid "Request Date" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_hr_dasboard +msgid "Dashboard" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_purchase_root +msgid "Purchases" +msgstr "" + +#. module: base +#: model:res.country,name:base.md +msgid "Moldavia" +msgstr "" + +#. module: base +#: view:ir.module.module:0 +msgid "Features" +msgstr "" + +#. module: base +#: view:ir.module.module:0 +#: report:ir.module.reference.graph:0 +msgid "Version" +msgstr "" + +#. module: base +#: view:ir.model.access:0 +#: field:ir.model.access,perm_read:0 +#: view:ir.rule:0 +msgid "Read Access" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_exports +msgid "ir.exports" +msgstr "" + +#. module: base +#: code:addons/base/module/wizard/base_update_translations.py:38 +#, python-format +msgid "No language with code \"%s\" exists" +msgstr "" + +#. module: base +#: code:addons/base/publisher_warranty/publisher_warranty.py:163 +#, python-format +msgid "Error during communication with the publisher warranty server." +msgstr "" + +#. module: base +#: help:ir.actions.server,email:0 +msgid "" +"Provides the fields that will be used to fetch the email address, e.g. when " +"you select the invoice, then `object.invoice_address_id.email` is the field " +"which gives the correct address" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "%Y - Year with century." +msgstr "" + +#. module: base +#: report:ir.module.reference.graph:0 +msgid "-" +msgstr "" + +#. module: base +#: view:publisher_warranty.contract.wizard:0 +msgid "" +"This wizard helps you register a publisher warranty contract in your OpenERP " +"system. After the contract has been registered, you will be able to send " +"issues directly to OpenERP." +msgstr "" + +#. module: base +#: code:addons/orm.py:1744 +#, python-format +msgid "The search method is not implemented on this object !" +msgstr "" + +#. module: base +#: view:wizard.ir.model.menu.create:0 +msgid "Create _Menu" +msgstr "" + +#. module: base +#: field:res.payterm,name:0 +msgid "Payment Term (short name)" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_bank +#: view:res.bank:0 +#: field:res.partner.bank,bank:0 +msgid "Bank" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_exports_line +msgid "ir.exports.line" +msgstr "" + +#. module: base +#: help:base.language.install,overwrite:0 +msgid "" +"If you check this box, your customized translations will be overwritten and " +"replaced by the official ones." +msgstr "" + +#. module: base +#: field:ir.actions.report.xml,report_rml:0 +msgid "Main report file path" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.ir_action_report_xml +#: field:ir.module.module,reports_by_module:0 +#: model:ir.ui.menu,name:base.menu_ir_action_report_xml +msgid "Reports" +msgstr "" + +#. module: base +#: help:ir.actions.act_window.view,multi:0 +#: help:ir.actions.report.xml,multi:0 +msgid "" +"If set to true, the action will not be displayed on the right toolbar of a " +"form view." +msgstr "" + +#. module: base +#: field:workflow,on_create:0 +msgid "On Create" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_model.py:607 +#, python-format +msgid "" +"'%s' contains too many dots. XML ids should not contain dots ! These are " +"used to refer to other modules data, as in module.reference_id" +msgstr "" + +#. module: base +#: field:partner.sms.send,user:0 +#: field:res.config.users,login:0 +#: field:res.users,login:0 +msgid "Login" +msgstr "" + +#. module: base +#: view:ir.actions.server:0 +msgid "" +"Access all the fields related to the current object using expressions, i.e. " +"object.partner_id.name " +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_country_state +msgid "Country state" +msgstr "" + +#. module: base +#: selection:ir.property,type:0 +msgid "Float" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_request_link +msgid "res.request.link" +msgstr "" + +#. module: base +#: field:ir.actions.wizard,name:0 +msgid "Wizard Info" +msgstr "" + +#. module: base +#: view:base.language.export:0 +#: model:ir.actions.act_window,name:base.action_wizard_lang_export +#: model:ir.ui.menu,name:base.menu_wizard_lang_export +msgid "Export Translation" +msgstr "" + +#. module: base +#: help:res.log,secondary:0 +msgid "" +"Do not display this log if it belongs to the same object the user is working " +"on" +msgstr "" + +#. module: base +#: model:res.country,name:base.tp +msgid "East Timor" +msgstr "" + +#. module: base +#: model:res.company,follow_up_msg:base.main_company +msgid "" +"Date : %(date)s\n" +"\n" +"Dear %(partner_name)s,\n" +"\n" +"Please find in attachment a reminder of all your unpaid invoices, for a " +"total amount due of:\n" +"\n" +"%(followup_amount).2f %(company_currency)s\n" +"\n" +"Thanks,\n" +"--\n" +"%(user_signature)s\n" +"%(company_name)s" +msgstr "" + +#. module: base +#: field:res.currency,accuracy:0 +msgid "Computational Accuracy" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Sinhalese / සිංහල" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_wizard_ir_model_menu_create_line +msgid "wizard.ir.model.menu.create.line" +msgstr "" + +#. module: base +#: field:ir.attachment,res_id:0 +msgid "Attached ID" +msgstr "" + +#. module: base +#: view:ir.sequence:0 +msgid "Day: %(day)s" +msgstr "" + +#. module: base +#: model:res.country,name:base.mv +msgid "Maldives" +msgstr "馬爾代夫" + +#. module: base +#: help:ir.values,res_id:0 +msgid "Keep 0 if the action must appear on all resources." +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_rule +msgid "ir.rule" +msgstr "" + +#. module: base +#: selection:ir.cron,interval_type:0 +msgid "Days" +msgstr "" + +#. module: base +#: help:ir.actions.server,condition:0 +msgid "" +"Condition that is to be tested before action is executed, e.g. " +"object.list_price > object.cost_price" +msgstr "" + +#. module: base +#: code:addons/base/res/partner/partner.py:155 +#: code:addons/base/res/res_company.py:66 +#, python-format +msgid " (copy)" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "7. %H:%M:%S ==> 18:25:20" +msgstr "" + +#. module: base +#: view:res.partner:0 +#: view:res.partner.category:0 +#: field:res.partner.category,partner_ids:0 +msgid "Partners" +msgstr "" + +#. module: base +#: field:res.partner.category,parent_left:0 +msgid "Left parent" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.res_widget_act_window +#: model:ir.ui.menu,name:base.menu_res_widget_act_window +msgid "Homepage Widgets" +msgstr "" + +#. module: base +#: help:ir.actions.server,message:0 +msgid "" +"Specify the message. You can use the fields from the object. e.g. `Dear [[ " +"object.partner_id.name ]]`" +msgstr "" + +#. module: base +#: field:ir.attachment,res_model:0 +msgid "Attached Model" +msgstr "" + +#. module: base +#: view:ir.rule:0 +msgid "Domain Setup" +msgstr "" + +#. module: base +#: field:ir.actions.server,trigger_name:0 +msgid "Trigger Name" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_model_access +msgid "ir.model.access" +msgstr "" + +#. module: base +#: field:ir.cron,priority:0 +#: field:res.request,priority:0 +#: field:res.request.link,priority:0 +msgid "Priority" +msgstr "" + +#. module: base +#: field:workflow.transition,act_from:0 +msgid "Source Activity" +msgstr "" + +#. module: base +#: view:ir.sequence:0 +msgid "Legend (for prefix, suffix)" +msgstr "" + +#. module: base +#: selection:ir.server.object.lines,type:0 +msgid "Formula" +msgstr "" + +#. module: base +#: code:addons/base/res/res_user.py:389 +#, python-format +msgid "Can not remove root user!" +msgstr "" + +#. module: base +#: model:res.country,name:base.mw +msgid "Malawi" +msgstr "馬拉維" + +#. module: base +#: code:addons/base/res/res_user.py:51 +#: code:addons/base/res/res_user.py:413 +#, python-format +msgid "%s (copy)" +msgstr "" + +#. module: base +#: field:res.partner.address,type:0 +msgid "Address Type" +msgstr "" + +#. module: base +#: view:ir.ui.menu:0 +msgid "Full Path" +msgstr "完整路徑" + +#. module: base +#: view:res.request:0 +msgid "References" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "" +"%U - Week number of the year (Sunday as the first day of the week) as a " +"decimal number [00,53]. All days in a new year preceding the first Sunday " +"are considered to be in week 0." +msgstr "" + +#. module: base +#: view:ir.ui.view:0 +msgid "Advanced" +msgstr "" + +#. module: base +#: model:res.country,name:base.fi +msgid "Finland" +msgstr "芬蘭" + +#. module: base +#: selection:ir.actions.act_window,view_type:0 +#: selection:ir.actions.act_window.view,view_mode:0 +#: view:ir.ui.view:0 +#: selection:ir.ui.view,type:0 +#: selection:wizard.ir.model.menu.create.line,view_type:0 +msgid "Tree" +msgstr "" + +#. module: base +#: help:res.config.users,password:0 +msgid "" +"Keep empty if you don't want the user to be able to connect on the system." +msgstr "" + +#. module: base +#: view:ir.actions.server:0 +msgid "Create / Write / Copy" +msgstr "" + +#. module: base +#: view:base.language.export:0 +msgid "https://help.launchpad.net/Translations" +msgstr "" + +#. module: base +#: field:ir.actions.act_window,view_mode:0 +msgid "View Mode" +msgstr "" + +#. module: base +#: view:base.language.import:0 +msgid "" +"When using CSV format, please also check that the first line of your file is " +"one of the following:" +msgstr "" + +#. module: base +#: code:addons/fields.py:114 +#, python-format +msgid "Not implemented search_memory method !" +msgstr "" + +#. module: base +#: view:res.log:0 +msgid "Logs" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Spanish / Español" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Korean (KP) / 한국어 (KP)" +msgstr "" + +#. module: base +#: view:base.module.update:0 +msgid "" +"This wizard will scan all module repositories on the server side to detect " +"newly added modules as well as any change to existing modules." +msgstr "" + +#. module: base +#: field:res.company,logo:0 +msgid "Logo" +msgstr "" + +#. module: base +#: view:res.partner.address:0 +msgid "Search Contact" +msgstr "" + +#. module: base +#: view:ir.module.module:0 +msgid "Uninstall (beta)" +msgstr "" + +#. module: base +#: selection:ir.actions.act_window,target:0 +#: selection:ir.actions.url,target:0 +msgid "New Window" +msgstr "" + +#. module: base +#: model:res.country,name:base.bs +msgid "Bahamas" +msgstr "" + +#. module: base +#: code:addons/base/res/partner/partner.py:250 +#, python-format +msgid "" +"Couldn't generate the next id because some partners have an alphabetic id !" +msgstr "" + +#. module: base +#: view:ir.attachment:0 +msgid "Attachment" +msgstr "" + +#. module: base +#: model:res.country,name:base.ie +msgid "Ireland" +msgstr "" + +#. module: base +#: field:base.module.update,update:0 +msgid "Number of modules updated" +msgstr "" + +#. module: base +#: code:addons/fields.py:100 +#, python-format +msgid "Not implemented set_memory method !" +msgstr "" + +#. module: base +#: view:workflow.activity:0 +msgid "Workflow Activity" +msgstr "" + +#. module: base +#: view:ir.rule:0 +msgid "" +"Example: GLOBAL_RULE_1 AND GLOBAL_RULE_2 AND ( (GROUP_A_RULE_1 AND " +"GROUP_A_RULE_2) OR (GROUP_B_RULE_1 AND GROUP_B_RULE_2) )" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,help:base.action_ui_view +msgid "" +"Views allows you to personalize each view of OpenERP. You can add new " +"fields, move fields, rename them or delete the ones that you do not need." +msgstr "" + +#. module: base +#: field:ir.actions.act_window,groups_id:0 +#: model:ir.actions.act_window,name:base.action_res_groups +#: view:ir.actions.report.xml:0 +#: field:ir.actions.report.xml,groups_id:0 +#: view:ir.actions.todo:0 +#: field:ir.actions.todo,groups_id:0 +#: field:ir.actions.wizard,groups_id:0 +#: view:ir.model:0 +#: field:ir.model.fields,groups:0 +#: field:ir.rule,groups:0 +#: view:ir.ui.menu:0 +#: field:ir.ui.menu,groups_id:0 +#: model:ir.ui.menu,name:base.menu_action_res_groups +#: field:res.config.users,groups_id:0 +#: view:res.groups:0 +#: view:res.users:0 +#: field:res.users,groups_id:0 +msgid "Groups" +msgstr "羣組" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Spanish (CL) / Español (CL)" +msgstr "西班牙文 (CL) / Español (CL)" + +#. module: base +#: view:res.config.users:0 +msgid "" +"Create additional users and assign them groups that will allow them to have " +"access to selected functionalities within the system. Click on 'Done' if you " +"do not wish to add more users at this stage, you can always do this later." +msgstr "" + +#. module: base +#: model:res.country,name:base.bz +msgid "Belize" +msgstr "伯利茲" + +#. module: base +#: model:res.country,name:base.ge +msgid "Georgia" +msgstr "格魯吉亞" + +#. module: base +#: model:res.country,name:base.pl +msgid "Poland" +msgstr "波蘭" + +#. module: base +#: help:ir.actions.act_window,view_mode:0 +msgid "" +"Comma-separated list of allowed view modes, such as 'form', 'tree', " +"'calendar', etc. (Default: tree,form)" +msgstr "" + +#. module: base +#: code:addons/orm.py:3147 +#, python-format +msgid "A document was modified since you last viewed it (%s:%d)" +msgstr "" + +#. module: base +#: view:workflow:0 +msgid "Workflow Editor" +msgstr "" + +#. module: base +#: selection:ir.module.module,state:0 +#: selection:ir.module.module.dependency,state:0 +msgid "To be removed" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_sequence +msgid "ir.sequence" +msgstr "" + +#. module: base +#: help:ir.actions.server,expression:0 +msgid "" +"Enter the field/expression that will return the list. E.g. select the sale " +"order in Object, and you can have loop on the sales order line. Expression = " +"`object.order_line`." +msgstr "" + +#. module: base +#: field:ir.property,fields_id:0 +#: selection:ir.translation,type:0 +#: field:multi_company.default,field_id:0 +msgid "Field" +msgstr "欄位" + +#. module: base +#: view:ir.rule:0 +msgid "Groups (no group = global)" +msgstr "" + +#. module: base +#: model:res.country,name:base.fo +msgid "Faroe Islands" +msgstr "法羅羣島" + +#. module: base +#: selection:res.config.users,view:0 +#: selection:res.config.view,view:0 +#: selection:res.users,view:0 +msgid "Simplified" +msgstr "" + +#. module: base +#: model:res.country,name:base.st +msgid "Saint Tome (Sao Tome) and Principe" +msgstr "" + +#. module: base +#: selection:res.partner.address,type:0 +msgid "Invoice" +msgstr "發票" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Portugese (BR) / Português (BR)" +msgstr "葡萄牙文 (BR) / Português (BR)" + +#. module: base +#: model:res.country,name:base.bb +msgid "Barbados" +msgstr "巴巴多斯" + +#. module: base +#: model:res.country,name:base.mg +msgid "Madagascar" +msgstr "馬達加斯加" + +#. module: base +#: code:addons/base/ir/ir_model.py:96 +#, python-format +msgid "" +"The Object name must start with x_ and not contain any special character !" +msgstr "" + +#. module: base +#: field:ir.actions.configuration.wizard,note:0 +msgid "Next Wizard" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_menu_admin +#: view:ir.ui.menu:0 +#: field:ir.ui.menu,name:0 +msgid "Menu" +msgstr "選單" + +#. module: base +#: field:res.currency,rate:0 +msgid "Current Rate" +msgstr "" + +#. module: base +#: field:ir.ui.view.custom,ref_id:0 +msgid "Original View" +msgstr "" + +#. module: base +#: view:ir.values:0 +msgid "Action To Launch" +msgstr "" + +#. module: base +#: field:ir.actions.url,target:0 +msgid "Action Target" +msgstr "" + +#. module: base +#: model:res.country,name:base.ai +msgid "Anguilla" +msgstr "安圭拉" + +#. module: base +#: field:ir.ui.view_sc,name:0 +msgid "Shortcut Name" +msgstr "" + +#. module: base +#: help:ir.actions.act_window,limit:0 +msgid "Default limit for the list view" +msgstr "" + +#. module: base +#: help:ir.actions.server,write_id:0 +msgid "" +"Provide the field name that the record id refers to for the write operation. " +"If it is empty it will refer to the active id of the object." +msgstr "" + +#. module: base +#: model:res.country,name:base.zw +msgid "Zimbabwe" +msgstr "津巴布韋" + +#. module: base +#: view:base.module.update:0 +msgid "Please be patient, as this operation may take a few seconds..." +msgstr "" + +#. module: base +#: help:ir.values,action_id:0 +msgid "This field is not used, it only helps you to select the right action." +msgstr "" + +#. module: base +#: field:ir.actions.server,email:0 +msgid "Email Address" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "French (BE) / Français (BE)" +msgstr "法文 (BE) / Français (BE)" + +#. module: base +#: view:ir.actions.server:0 +#: field:workflow.activity,action_id:0 +msgid "Server Action" +msgstr "" + +#. module: base +#: model:res.country,name:base.tt +msgid "Trinidad and Tobago" +msgstr "千里達" + +#. module: base +#: model:res.country,name:base.lv +msgid "Latvia" +msgstr "拉脫維亞" + +#. module: base +#: view:ir.values:0 +msgid "Values" +msgstr "" + +#. module: base +#: view:ir.actions.server:0 +msgid "Field Mappings" +msgstr "" + +#. module: base +#: view:base.language.export:0 +msgid "Export Translations" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_custom +msgid "Customization" +msgstr "" + +#. module: base +#: model:res.country,name:base.py +msgid "Paraguay" +msgstr "巴拉圭" + +#. module: base +#: model:ir.model,name:base.model_ir_actions_act_window_close +msgid "ir.actions.act_window_close" +msgstr "" + +#. module: base +#: field:ir.server.object.lines,col1:0 +msgid "Destination" +msgstr "" + +#. module: base +#: model:res.country,name:base.lt +msgid "Lithuania" +msgstr "立陶宛" + +#. module: base +#: model:ir.actions.act_window,name:base.action_view_partner_clear_ids +#: model:ir.model,name:base.model_partner_clear_ids +#: view:partner.clear.ids:0 +msgid "Clear IDs" +msgstr "" + +#. module: base +#: help:ir.cron,model:0 +msgid "" +"Name of object whose function will be called when this scheduler will run. " +"e.g. 'res.partener'" +msgstr "" + +#. module: base +#: code:addons/orm.py:1040 +#, python-format +msgid "The perm_read method is not implemented on this object !" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "%y - Year without century [00,99]." +msgstr "" + +#. module: base +#: model:res.country,name:base.si +msgid "Slovenia" +msgstr "斯洛文尼亞" + +#. module: base +#: model:res.country,name:base.pk +msgid "Pakistan" +msgstr "巴基斯坦" + +#. module: base +#: code:addons/orm.py:1350 +#, python-format +msgid "Invalid Object Architecture!" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_email_gateway_form +msgid "Messages" +msgstr "訊息" + +#. module: base +#: code:addons/base/ir/ir_model.py:303 +#: code:addons/base/ir/ir_model.py:317 +#: code:addons/base/ir/ir_model.py:319 +#: code:addons/base/ir/ir_model.py:321 +#: code:addons/base/ir/ir_model.py:328 +#: code:addons/base/ir/ir_model.py:331 +#: code:addons/base/module/wizard/base_update_translations.py:38 +#, python-format +msgid "Error!" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "%p - Equivalent of either AM or PM." +msgstr "" + +#. module: base +#: view:ir.actions.server:0 +msgid "Iteration Actions" +msgstr "" + +#. module: base +#: help:multi_company.default,company_id:0 +msgid "Company where the user is connected" +msgstr "" + +#. module: base +#: field:publisher_warranty.contract,date_stop:0 +msgid "Ending Date" +msgstr "" + +#. module: base +#: model:res.country,name:base.nz +msgid "New Zealand" +msgstr "" + +#. module: base +#: code:addons/orm.py:3366 +#, python-format +msgid "" +"One of the records you are trying to modify has already been deleted " +"(Document type: %s)." +msgstr "" + +#. module: base +#: model:ir.actions.act_window,help:base.action_country +msgid "" +"Display and manage the list of all countries that can be assigned to your " +"partner records. You can create or delete countries to make sure the ones " +"you are working on will be maintained." +msgstr "" + +#. module: base +#: model:res.partner.category,name:base.res_partner_category_7 +msgid "Openstuff.net" +msgstr "" + +#. module: base +#: model:res.country,name:base.nf +msgid "Norfolk Island" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Korean (KR) / 한국어 (KR)" +msgstr "" + +#. module: base +#: help:ir.model.fields,model:0 +msgid "The technical name of the model this field belongs to" +msgstr "" + +#. module: base +#: field:ir.actions.server,action_id:0 +#: selection:ir.actions.server,state:0 +msgid "Client Action" +msgstr "" + +#. module: base +#: model:res.country,name:base.bd +msgid "Bangladesh" +msgstr "" + +#. module: base +#: constraint:res.company:0 +msgid "Error! You can not create recursive companies." +msgstr "" + +#. module: base +#: selection:publisher_warranty.contract,state:0 +msgid "Valid" +msgstr "" + +#. module: base +#: selection:ir.translation,type:0 +msgid "XSL" +msgstr "" + +#. module: base +#: code:addons/base/module/module.py:322 +#, python-format +msgid "Can not upgrade module '%s'. It is not installed." +msgstr "" + +#. module: base +#: model:res.country,name:base.cu +msgid "Cuba" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_partner_event +msgid "res.partner.event" +msgstr "" + +#. module: base +#: model:res.widget,title:base.facebook_widget +msgid "Facebook" +msgstr "" + +#. module: base +#: model:res.country,name:base.am +msgid "Armenia" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.ir_property_form +#: model:ir.ui.menu,name:base.menu_ir_property_form_all +msgid "Configuration Parameters" +msgstr "" + +#. module: base +#: constraint:ir.cron:0 +msgid "Invalid arguments" +msgstr "" + +#. module: base +#: model:res.country,name:base.se +msgid "Sweden" +msgstr "" + +#. module: base +#: selection:ir.actions.act_window.view,view_mode:0 +#: selection:ir.ui.view,type:0 +#: selection:wizard.ir.model.menu.create.line,view_type:0 +msgid "Gantt" +msgstr "" + +#. module: base +#: view:ir.property:0 +msgid "Property" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_partner_bank_type +#: view:res.partner.bank.type:0 +msgid "Bank Account Type" +msgstr "" + +#. module: base +#: field:base.language.export,config_logo:0 +#: field:base.language.import,config_logo:0 +#: field:base.language.install,config_logo:0 +#: field:base.module.import,config_logo:0 +#: field:base.module.update,config_logo:0 +#: field:base.update.translations,config_logo:0 +#: field:ir.actions.configuration.wizard,config_logo:0 +#: field:ir.wizard.screen,config_logo:0 +#: field:publisher_warranty.contract.wizard,config_logo:0 +#: field:res.config,config_logo:0 +#: field:res.config.installer,config_logo:0 +#: field:res.config.users,config_logo:0 +#: field:res.config.view,config_logo:0 +msgid "Image" +msgstr "" + +#. module: base +#: view:ir.actions.server:0 +msgid "Iteration Action Configuration" +msgstr "" + +#. module: base +#: selection:publisher_warranty.contract,state:0 +msgid "Canceled" +msgstr "" + +#. module: base +#: model:res.country,name:base.at +msgid "Austria" +msgstr "" + +#. module: base +#: selection:base.language.install,state:0 +#: selection:base.module.import,state:0 +#: selection:base.module.update,state:0 +msgid "done" +msgstr "" + +#. module: base +#: selection:ir.actions.act_window.view,view_mode:0 +#: model:ir.ui.menu,name:base.menu_calendar_configuration +#: selection:ir.ui.view,type:0 +#: selection:wizard.ir.model.menu.create.line,view_type:0 +msgid "Calendar" +msgstr "" + +#. module: base +#: field:res.partner.address,partner_id:0 +msgid "Partner Name" +msgstr "" + +#. module: base +#: field:workflow.activity,signal_send:0 +msgid "Signal (subflow.*)" +msgstr "" + +#. module: base +#: model:res.partner.category,name:base.res_partner_category_17 +msgid "HR sector" +msgstr "" + +#. module: base +#: code:addons/orm.py:3817 +#, python-format +msgid "" +"Invalid \"order\" specified. A valid \"order\" specification is a comma-" +"separated list of valid field names (optionally followed by asc/desc for the " +"direction)" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_module_module_dependency +msgid "Module dependency" +msgstr "" + +#. module: base +#: selection:publisher_warranty.contract.wizard,state:0 +msgid "Draft" +msgstr "" + +#. module: base +#: selection:res.config.users,view:0 +#: selection:res.config.view,view:0 +#: selection:res.users,view:0 +msgid "Extended" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,help:base.action_partner_title_contact +msgid "" +"Manage the contact titles you want to have available in your system and the " +"way you want to print them in letters and other documents. Some example: " +"Mr., Mrs. " +msgstr "" + +#. module: base +#: field:res.company,rml_footer1:0 +msgid "Report Footer 1" +msgstr "" + +#. module: base +#: field:res.company,rml_footer2:0 +msgid "Report Footer 2" +msgstr "" + +#. module: base +#: view:ir.model.access:0 +#: view:res.groups:0 +#: field:res.groups,model_access:0 +msgid "Access Controls" +msgstr "" + +#. module: base +#: view:ir.module.module:0 +#: field:ir.module.module,dependencies_id:0 +msgid "Dependencies" +msgstr "" + +#. module: base +#: field:multi_company.default,company_id:0 +msgid "Main Company" +msgstr "" + +#. module: base +#: field:ir.ui.menu,web_icon_hover:0 +msgid "Web Icon File (hover)" +msgstr "" + +#. module: base +#: view:ir.actions.server:0 +msgid "" +"If you use a formula type, use a python expression using the variable " +"'object'." +msgstr "" + +#. module: base +#: field:res.partner.address,birthdate:0 +msgid "Birthdate" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_partner_title_contact +#: model:ir.ui.menu,name:base.menu_partner_title_contact +msgid "Contact Titles" +msgstr "" + +#. module: base +#: view:base.language.import:0 +msgid "" +"Please double-check that the file encoding is set to UTF-8 (sometimes called " +"Unicode) when the translator exports it." +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Spanish (DO) / Español (DO)" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_workflow_activity +msgid "workflow.activity" +msgstr "" + +#. module: base +#: help:ir.ui.view_sc,res_id:0 +msgid "" +"Reference of the target resource, whose model/table depends on the 'Resource " +"Name' field." +msgstr "" + +#. module: base +#: field:ir.model.fields,select_level:0 +msgid "Searchable" +msgstr "" + +#. module: base +#: model:res.country,name:base.uy +msgid "Uruguay" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Finnish / Suomi" +msgstr "" + +#. module: base +#: field:ir.rule,perm_write:0 +msgid "Apply For Write" +msgstr "" + +#. module: base +#: field:ir.sequence,prefix:0 +msgid "Prefix" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "German / Deutsch" +msgstr "" + +#. module: base +#: help:ir.actions.server,trigger_name:0 +msgid "Select the Signal name that is to be used as the trigger." +msgstr "" + +#. module: base +#: view:ir.actions.server:0 +msgid "Fields Mapping" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Portugese / Português" +msgstr "" + +#. module: base +#: model:res.partner.title,name:base.res_partner_title_sir +msgid "Sir" +msgstr "" + +#. module: base +#: code:addons/orm.py:1622 +#, python-format +msgid "There is no view of type '%s' defined for the structure!" +msgstr "" + +#. module: base +#: field:ir.default,ref_id:0 +msgid "ID Ref." +msgstr "" + +#. module: base +#: model:ir.actions.server,name:base.action_start_configurator +#: model:ir.ui.menu,name:base.menu_view_base_module_configuration +msgid "Start Configuration" +msgstr "" + +#. module: base +#: model:res.country,name:base.mt +msgid "Malta" +msgstr "" + +#. module: base +#: field:ir.actions.server,fields_lines:0 +msgid "Field Mappings." +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_module_module +#: view:ir.model.data:0 +#: field:ir.model.data,module:0 +#: view:ir.module.module:0 +#: field:ir.module.module.dependency,module_id:0 +#: report:ir.module.reference.graph:0 +#: field:ir.translation,module:0 +msgid "Module" +msgstr "" + +#. module: base +#: field:ir.attachment,description:0 +#: view:ir.module.module:0 +#: field:ir.module.module,description:0 +#: field:res.partner.bank,name:0 +#: view:res.partner.event:0 +#: field:res.partner.event,description:0 +#: view:res.request:0 +msgid "Description" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_workflow_instance_form +#: model:ir.ui.menu,name:base.menu_workflow_instance +msgid "Instances" +msgstr "" + +#. module: base +#: model:res.country,name:base.aq +msgid "Antarctica" +msgstr "" + +#. module: base +#: field:ir.actions.report.xml,auto:0 +msgid "Custom python parser" +msgstr "" + +#. module: base +#: view:base.language.import:0 +msgid "_Import" +msgstr "" + +#. module: base +#: view:res.partner.canal:0 +msgid "Channel" +msgstr "" + +#. module: base +#: field:res.lang,grouping:0 +msgid "Separator Format" +msgstr "" + +#. module: base +#: selection:publisher_warranty.contract,state:0 +msgid "Unvalidated" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.next_id_9 +msgid "Database Structure" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_partner_mass_mail +#: model:ir.model,name:base.model_partner_wizard_spam +#: view:partner.wizard.spam:0 +msgid "Mass Mailing" +msgstr "" + +#. module: base +#: model:res.country,name:base.yt +msgid "Mayotte" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_actions.py:597 +#, python-format +msgid "Please specify an action to launch !" +msgstr "" + +#. module: base +#: view:res.payterm:0 +msgid "Payment Term" +msgstr "" + +#. module: base +#: selection:res.lang,direction:0 +msgid "Right-to-Left" +msgstr "" + +#. module: base +#: view:ir.actions.act_window:0 +#: model:ir.actions.act_window,name:base.actions_ir_filters_view +#: view:ir.filters:0 +#: model:ir.model,name:base.model_ir_filters +#: model:ir.ui.menu,name:base.menu_ir_filters +msgid "Filters" +msgstr "" + +#. module: base +#: code:addons/orm.py:758 +#, python-format +msgid "Please check that all your lines have %d columns." +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.ir_cron_act +#: view:ir.cron:0 +#: model:ir.ui.menu,name:base.menu_ir_cron_act +msgid "Scheduled Actions" +msgstr "" + +#. module: base +#: field:res.partner.address,title:0 +#: field:res.partner.title,name:0 +#: field:res.widget,title:0 +msgid "Title" +msgstr "" + +#. module: base +#: help:ir.property,res_id:0 +msgid "If not set, acts as a default value for new resources" +msgstr "" + +#. module: base +#: code:addons/orm.py:3448 +#, python-format +msgid "Recursivity Detected." +msgstr "" + +#. module: base +#: code:addons/base/module/module.py:262 +#, python-format +msgid "Recursion error in modules dependencies !" +msgstr "" + +#. module: base +#: view:base.language.install:0 +msgid "" +"This wizard helps you add a new language to your OpenERP system. After " +"loading a new language it becomes available as default interface language " +"for users and partners." +msgstr "" + +#. module: base +#: view:ir.model:0 +msgid "Create a Menu" +msgstr "" + +#. module: base +#: help:res.partner,vat:0 +msgid "" +"Value Added Tax number. Check the box if the partner is subjected to the " +"VAT. Used by the VAT legal statement." +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_maintenance_contract +msgid "maintenance.contract" +msgstr "" + +#. module: base +#: model:res.country,name:base.ru +msgid "Russian Federation" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Urdu / اردو" +msgstr "" + +#. module: base +#: field:res.company,name:0 +msgid "Company Name" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_country +#: model:ir.ui.menu,name:base.menu_country_partner +msgid "Countries" +msgstr "" + +#. module: base +#: selection:ir.translation,type:0 +msgid "RML (deprecated - use Report)" +msgstr "" + +#. module: base +#: view:ir.rule:0 +msgid "Record rules" +msgstr "" + +#. module: base +#: view:ir.property:0 +msgid "Field Information" +msgstr "" + +#. module: base +#: view:ir.actions.todo:0 +msgid "Search Actions" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_view_partner_wizard_ean_check +#: view:partner.wizard.ean.check:0 +msgid "Ean check" +msgstr "" + +#. module: base +#: field:res.partner,vat:0 +msgid "VAT" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "12. %w ==> 5 ( Friday is the 6th day)" +msgstr "" + +#. module: base +#: constraint:res.partner.category:0 +msgid "Error ! You can not create recursive categories." +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "%x - Appropriate date representation." +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "%d - Day of the month [01,31]." +msgstr "" + +#. module: base +#: model:res.country,name:base.tj +msgid "Tajikistan" +msgstr "" + +#. module: base +#: selection:ir.module.module,license:0 +msgid "GPL-2 or later version" +msgstr "" + +#. module: base +#: model:res.partner.title,shortcut:base.res_partner_title_sir +msgid "M." +msgstr "" + +#. module: base +#: code:addons/base/module/module.py:429 +#, python-format +msgid "" +"Can not create the module file:\n" +" %s" +msgstr "" + +#. module: base +#: code:addons/orm.py:2973 +#, python-format +msgid "" +"Operation prohibited by access rules, or performed on an already deleted " +"document (Operation: read, Document type: %s)." +msgstr "" + +#. module: base +#: model:res.country,name:base.nr +msgid "Nauru" +msgstr "瑙魯" + +#. module: base +#: code:addons/base/module/module.py:200 +#, python-format +msgid "The certificate ID of the module must be unique !" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_property +msgid "ir.property" +msgstr "" + +#. module: base +#: selection:ir.actions.act_window,view_type:0 +#: selection:ir.actions.act_window.view,view_mode:0 +#: view:ir.ui.view:0 +#: selection:ir.ui.view,type:0 +#: selection:wizard.ir.model.menu.create.line,view_type:0 +msgid "Form" +msgstr "" + +#. module: base +#: model:res.country,name:base.me +msgid "Montenegro" +msgstr "黑山" + +#. module: base +#: view:ir.cron:0 +msgid "Technical Data" +msgstr "技術資料" + +#. module: base +#: view:res.partner:0 +#: field:res.partner,category_id:0 +msgid "Categories" +msgstr "分類" + +#. module: base +#: view:base.language.import:0 +msgid "" +"If you need another language than the official ones available, you can " +"import a language pack from here. Other OpenERP languages than the official " +"ones can be found on launchpad." +msgstr "" + +#. module: base +#: view:ir.module.module:0 +#: selection:ir.module.module,state:0 +#: selection:ir.module.module.dependency,state:0 +msgid "To be upgraded" +msgstr "" + +#. module: base +#: model:res.country,name:base.ly +msgid "Libya" +msgstr "利比亞" + +#. module: base +#: model:res.country,name:base.cf +msgid "Central African Republic" +msgstr "中非共和國" + +#. module: base +#: model:res.country,name:base.li +msgid "Liechtenstein" +msgstr "列支敦士登" + +#. module: base +#: model:ir.model,name:base.model_partner_sms_send +#: view:partner.sms.send:0 +msgid "Send SMS" +msgstr "" + +#. module: base +#: field:res.partner,ean13:0 +msgid "EAN13" +msgstr "" + +#. module: base +#: code:addons/orm.py:1622 +#, python-format +msgid "Invalid Architecture!" +msgstr "" + +#. module: base +#: model:res.country,name:base.pt +msgid "Portugal" +msgstr "葡萄牙" + +#. module: base +#: sql_constraint:ir.model.data:0 +msgid "" +"You cannot have multiple records with the same id for the same module !" +msgstr "" + +#. module: base +#: field:ir.module.module,certificate:0 +msgid "Quality Certificate" +msgstr "品質證書" + +#. module: base +#: view:res.lang:0 +msgid "6. %d, %m ==> 05, 12" +msgstr "" + +#. module: base +#: field:res.config.users,date:0 +#: field:res.users,date:0 +msgid "Last Connection" +msgstr "" + +#. module: base +#: field:ir.actions.act_window,help:0 +msgid "Action description" +msgstr "" + +#. module: base +#: help:res.partner,customer:0 +msgid "Check this box if the partner is a customer." +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.res_lang_act_window +#: model:ir.model,name:base.model_res_lang +#: model:ir.ui.menu,name:base.menu_res_lang_act_window +#: view:res.lang:0 +msgid "Languages" +msgstr "語言" + +#. module: base +#: selection:workflow.activity,join_mode:0 +#: selection:workflow.activity,split_mode:0 +msgid "Xor" +msgstr "" + +#. module: base +#: model:res.country,name:base.ec +msgid "Ecuador" +msgstr "厄瓜多爾" + +#. module: base +#: code:addons/base/module/wizard/base_export_language.py:52 +#, python-format +msgid "" +"Save this document to a .CSV file and open it with your favourite " +"spreadsheet software. The file encoding is UTF-8. You have to translate the " +"latest column before reimporting it." +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_partner_customer_form +#: model:ir.actions.act_window,name:base.action_partner_form +#: model:ir.ui.menu,name:base.menu_partner_form +#: view:res.partner:0 +msgid "Customers" +msgstr "" + +#. module: base +#: model:res.country,name:base.au +msgid "Australia" +msgstr "澳洲" + +#. module: base +#: help:res.partner,lang:0 +msgid "" +"If the selected language is loaded in the system, all documents related to " +"this partner will be printed in this language. If not, it will be english." +msgstr "" + +#. module: base +#: report:ir.module.reference.graph:0 +msgid "Menu :" +msgstr "" + +#. module: base +#: selection:ir.model.fields,state:0 +msgid "Base Field" +msgstr "" + +#. module: base +#: view:publisher_warranty.contract:0 +msgid "Validate" +msgstr "" + +#. module: base +#: field:ir.actions.todo,restart:0 +msgid "Restart" +msgstr "" + +#. module: base +#: field:ir.actions.report.xml,report_sxw_content:0 +#: field:ir.actions.report.xml,report_sxw_content_data:0 +msgid "SXW content" +msgstr "" + +#. module: base +#: view:ir.actions.wizard:0 +#: field:wizard.ir.model.menu.create.line,wizard_id:0 +msgid "Wizard" +msgstr "" + +#. module: base +#: view:ir.cron:0 +msgid "Action to Trigger" +msgstr "" + +#. module: base +#: code:addons/base/res/res_user.py:136 +#, python-format +msgid "\"email_from\" needs to be set to send welcome mails to users" +msgstr "" + +#. module: base +#: selection:ir.translation,type:0 +msgid "Constraint" +msgstr "約束" + +#. module: base +#: selection:ir.values,key:0 +#: selection:res.partner.address,type:0 +msgid "Default" +msgstr "預設" + +#. module: base +#: view:ir.model.fields:0 +#: field:ir.model.fields,required:0 +#: field:res.partner.bank.type.field,required:0 +msgid "Required" +msgstr "必要" + +#. module: base +#: view:res.users:0 +msgid "Default Filters" +msgstr "" + +#. module: base +#: field:res.request.history,name:0 +msgid "Summary" +msgstr "摘要" + +#. module: base +#: field:multi_company.default,expression:0 +msgid "Expression" +msgstr "" + +#. module: base +#: help:ir.actions.server,subject:0 +msgid "" +"Specify the subject. You can use fields from the object, e.g. `Hello [[ " +"object.partner_id.name ]]`" +msgstr "" + +#. module: base +#: view:res.company:0 +msgid "Header/Footer" +msgstr "" + +#. module: base +#: help:ir.actions.act_window,help:0 +msgid "" +"Optional help text for the users with a description of the target view, such " +"as its usage and purpose." +msgstr "" + +#. module: base +#: model:res.country,name:base.va +msgid "Holy See (Vatican City State)" +msgstr "梵蒂岡" + +#. module: base +#: field:base.module.import,module_file:0 +msgid "Module .ZIP file" +msgstr "" + +#. module: base +#: field:ir.ui.view,xml_id:0 +msgid "XML ID" +msgstr "" + +#. module: base +#: model:res.partner.category,name:base.res_partner_category_16 +msgid "Telecom sector" +msgstr "電訊範疇" + +#. module: base +#: field:workflow.transition,trigger_model:0 +msgid "Trigger Object" +msgstr "" + +#. module: base +#: view:res.users:0 +msgid "Current Activity" +msgstr "" + +#. module: base +#: view:workflow.activity:0 +#: field:workflow.activity,in_transitions:0 +msgid "Incoming Transitions" +msgstr "" + +#. module: base +#: model:res.country,name:base.sr +msgid "Suriname" +msgstr "蘇里南" + +#. module: base +#: model:ir.ui.menu,name:base.marketing_menu +msgid "Marketing" +msgstr "營銷" + +#. module: base +#: view:res.partner.bank:0 +#: model:res.partner.bank.type,name:base.bank_normal +msgid "Bank account" +msgstr "銀行帳戶" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Spanish (HN) / Español (HN)" +msgstr "西班牙文 (HN) / Español (HN)" + +#. module: base +#: view:ir.sequence.type:0 +msgid "Sequence Type" +msgstr "" + +#. module: base +#: view:ir.ui.view.custom:0 +msgid "Customized Architecture" +msgstr "" + +#. module: base +#: field:ir.module.module,license:0 +msgid "License" +msgstr "" + +#. module: base +#: field:ir.attachment,url:0 +msgid "Url" +msgstr "" + +#. module: base +#: selection:ir.actions.todo,restart:0 +msgid "Always" +msgstr "" + +#. module: base +#: selection:ir.translation,type:0 +msgid "SQL Constraint" +msgstr "" + +#. module: base +#: field:ir.actions.server,srcmodel_id:0 +#: field:ir.model.fields,model_id:0 +msgid "Model" +msgstr "" + +#. module: base +#: view:base.language.install:0 +msgid "" +"The selected language has been successfully installed. You must change the " +"preferences of the user and open a new menu to view the changes." +msgstr "" + +#. module: base +#: sql_constraint:ir.config_parameter:0 +msgid "Key must be unique." +msgstr "" + +#. module: base +#: view:ir.actions.act_window:0 +msgid "Open a Window" +msgstr "" + +#. module: base +#: model:res.country,name:base.gq +msgid "Equatorial Guinea" +msgstr "赤道畿內亞" + +#. module: base +#: view:base.module.import:0 +#: model:ir.actions.act_window,name:base.action_view_base_module_import +msgid "Module Import" +msgstr "" + +#. module: base +#: field:res.bank,zip:0 +#: field:res.partner.address,zip:0 +#: field:res.partner.bank,zip:0 +msgid "Zip" +msgstr "" + +#. module: base +#: view:ir.module.module:0 +#: field:ir.module.module,author:0 +msgid "Author" +msgstr "" + +#. module: base +#: model:res.country,name:base.mk +msgid "FYROM" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "%c - Appropriate date and time representation." +msgstr "" + +#. module: base +#: code:addons/base/res/res_config.py:422 +#, python-format +msgid "" +"Your database is now fully configured.\n" +"\n" +"Click 'Continue' and enjoy your OpenERP experience..." +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Hebrew / עִבְרִי" +msgstr "希伯來文 / עִבְרִי" + +#. module: base +#: model:res.country,name:base.bo +msgid "Bolivia" +msgstr "玻利維亞" + +#. module: base +#: model:res.country,name:base.gh +msgid "Ghana" +msgstr "加納" + +#. module: base +#: field:res.lang,direction:0 +msgid "Direction" +msgstr "方向" + +#. module: base +#: view:ir.actions.act_window:0 +#: model:ir.actions.act_window,name:base.action_ui_view +#: field:ir.actions.act_window,view_ids:0 +#: field:ir.actions.act_window,views:0 +#: field:ir.module.module,views_by_module:0 +#: model:ir.ui.menu,name:base.menu_action_ui_view +#: view:ir.ui.view:0 +msgid "Views" +msgstr "檢視" + +#. module: base +#: view:res.groups:0 +#: field:res.groups,rule_groups:0 +msgid "Rules" +msgstr "規則" + +#. module: base +#: code:addons/base/module/module.py:216 +#, python-format +msgid "You try to remove a module that is installed or will be installed" +msgstr "" + +#. module: base +#: view:base.module.upgrade:0 +msgid "The selected modules have been updated / installed !" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Spanish (PR) / Español (PR)" +msgstr "西班牙文 (PR) / Español (PR)" + +#. module: base +#: model:res.country,name:base.gt +msgid "Guatemala" +msgstr "危地馬拉" + +#. module: base +#: model:ir.actions.act_window,name:base.action_workflow_form +#: model:ir.ui.menu,name:base.menu_low_workflow +#: model:ir.ui.menu,name:base.menu_workflow +#: model:ir.ui.menu,name:base.menu_workflow_root +msgid "Workflows" +msgstr "" + +#. module: base +#: field:ir.translation,xml_id:0 +msgid "XML Id" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_config_user_form +msgid "Create Users" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_partner_title +msgid "res.partner.title" +msgstr "" + +#. module: base +#: view:ir.values:0 +msgid "tree_but_action, client_print_multi" +msgstr "" + +#. module: base +#: model:res.partner.category,name:base.res_partner_category_retailers0 +msgid "Retailers" +msgstr "零售商" + +#. module: base +#: help:ir.cron,priority:0 +msgid "" +"0=Very Urgent\n" +"10=Not urgent" +msgstr "" + +#. module: base +#: view:res.config:0 +#: view:res.config.installer:0 +msgid "Skip" +msgstr "" + +#. module: base +#: model:res.country,name:base.ls +msgid "Lesotho" +msgstr "萊索托" + +#. module: base +#: code:addons/base/ir/ir_model.py:114 +#, python-format +msgid "You can not remove the model '%s' !" +msgstr "" + +#. module: base +#: model:res.country,name:base.ke +msgid "Kenya" +msgstr "肯雅" + +#. module: base +#: view:res.partner.event:0 +msgid "Event" +msgstr "活動" + +#. module: base +#: model:ir.ui.menu,name:base.menu_custom_reports +msgid "Custom Reports" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Abkhazian / аҧсуа" +msgstr "阿布哈茲文 / аҧсуа" + +#. module: base +#: view:base.module.configuration:0 +msgid "System Configuration Done" +msgstr "" + +#. module: base +#: code:addons/orm.py:929 +#, python-format +msgid "Error occurred while validating the field(s) %s: %s" +msgstr "" + +#. module: base +#: view:ir.property:0 +msgid "Generic" +msgstr "通用" + +#. module: base +#: model:res.country,name:base.sm +msgid "San Marino" +msgstr "聖馬力諾" + +#. module: base +#: model:res.country,name:base.bm +msgid "Bermuda" +msgstr "百慕達" + +#. module: base +#: model:res.country,name:base.pe +msgid "Peru" +msgstr "秘魯" + +#. module: base +#: selection:ir.model.fields,on_delete:0 +msgid "Set NULL" +msgstr "" + +#. module: base +#: model:res.country,name:base.bj +msgid "Benin" +msgstr "貝寧" + +#. module: base +#: code:addons/base/publisher_warranty/publisher_warranty.py:281 +#, python-format +msgid "That contract is already registered in the system." +msgstr "" + +#. module: base +#: help:ir.sequence,suffix:0 +msgid "Suffix value of the record for the sequence" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Spanish (PY) / Español (PY)" +msgstr "西班牙文 (PY) / Español (PY)" + +#. module: base +#: field:ir.config_parameter,key:0 +msgid "Key" +msgstr "" + +#. module: base +#: field:res.company,rml_header:0 +msgid "RML Header" +msgstr "" + +#. module: base +#: field:partner.sms.send,app_id:0 +msgid "API ID" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_model.py:486 +#, python-format +msgid "" +"You can not create this document (%s) ! Be sure your user belongs to one of " +"these groups: %s." +msgstr "" + +#. module: base +#: model:res.country,name:base.mu +msgid "Mauritius" +msgstr "毛里求斯" + +#. module: base +#: view:ir.model.access:0 +#: view:ir.rule:0 +msgid "Full Access" +msgstr "" + +#. module: base +#: view:ir.actions.act_window:0 +#: view:ir.actions.report.xml:0 +#: view:ir.actions.wizard:0 +#: view:ir.model.fields:0 +#: model:ir.ui.menu,name:base.menu_security +msgid "Security" +msgstr "保安" + +#. module: base +#: model:res.widget,title:base.openerp_favorites_twitter_widget +msgid "OpenERP Favorites" +msgstr "" + +#. module: base +#: model:res.country,name:base.za +msgid "South Africa" +msgstr "南非" + +#. module: base +#: view:ir.module.module:0 +#: selection:ir.module.module,state:0 +#: selection:ir.module.module.dependency,state:0 +msgid "Installed" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Ukrainian / українська" +msgstr "烏克蘭文 / українська" + +#. module: base +#: model:ir.actions.act_window,name:base.action_translation +#: model:ir.ui.menu,name:base.menu_action_translation +msgid "Translation Terms" +msgstr "" + +#. module: base +#: model:res.country,name:base.sn +msgid "Senegal" +msgstr "塞內加爾" + +#. module: base +#: model:res.country,name:base.hu +msgid "Hungary" +msgstr "匈牙利" + +#. module: base +#: model:ir.model,name:base.model_res_groups +msgid "res.groups" +msgstr "" + +#. module: base +#: model:res.country,name:base.br +msgid "Brazil" +msgstr "巴西" + +#. module: base +#: view:res.lang:0 +msgid "%M - Minute [00,59]." +msgstr "" + +#. module: base +#: selection:ir.module.module,license:0 +msgid "Affero GPL-3" +msgstr "" + +#. module: base +#: field:ir.sequence,number_next:0 +msgid "Next Number" +msgstr "" + +#. module: base +#: help:workflow.transition,condition:0 +msgid "Expression to be satisfied if we want the transition done." +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Spanish (PA) / Español (PA)" +msgstr "西班牙文 (PA) / Español (PA)" + +#. module: base +#: view:res.currency:0 +#: field:res.currency,rate_ids:0 +msgid "Rates" +msgstr "匯率" + +#. module: base +#: model:res.country,name:base.sy +msgid "Syria" +msgstr "敍利亞" + +#. module: base +#: view:res.lang:0 +msgid "======================================================" +msgstr "" + +#. module: base +#: help:ir.actions.server,mobile:0 +msgid "" +"Provides fields that be used to fetch the mobile number, e.g. you select the " +"invoice, then `object.invoice_address_id.mobile` is the field which gives " +"the correct mobile number" +msgstr "" + +#. module: base +#: view:base.module.upgrade:0 +msgid "System update completed" +msgstr "" + +#. module: base +#: selection:res.request,state:0 +msgid "draft" +msgstr "" + +#. module: base +#: selection:ir.property,type:0 +#: field:res.currency,date:0 +#: field:res.currency.rate,name:0 +#: field:res.partner,date:0 +#: field:res.partner.event,date:0 +#: field:res.request,date_sent:0 +msgid "Date" +msgstr "日期" + +#. module: base +#: field:ir.actions.report.xml,report_sxw:0 +msgid "SXW path" +msgstr "" + +#. module: base +#: view:ir.attachment:0 +msgid "Data" +msgstr "" + +#. module: base +#: field:ir.ui.menu,parent_id:0 +#: field:wizard.ir.model.menu.create,menu_id:0 +msgid "Parent Menu" +msgstr "" + +#. module: base +#: field:ir.rule,perm_unlink:0 +msgid "Apply For Delete" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_model.py:319 +#, python-format +msgid "Cannot rename column to %s, because that column already exists!" +msgstr "" + +#. module: base +#: view:ir.attachment:0 +msgid "Attached To" +msgstr "" + +#. module: base +#: field:res.lang,decimal_point:0 +msgid "Decimal Separator" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,help:base.action_res_groups +msgid "" +"A group is a set of functional areas that will be assigned to the user in " +"order to give them access and rights to specific applications and tasks in " +"the system. You can create custom groups or edit the ones existing by " +"default in order to customize the view of the menu that users will be able " +"to see. Whether they can have a read, write, create and delete access right " +"can be managed from here." +msgstr "" + +#. module: base +#: view:res.partner:0 +#: view:res.request:0 +#: field:res.request,history:0 +msgid "History" +msgstr "" + +#. module: base +#: field:ir.attachment,create_uid:0 +msgid "Creator" +msgstr "" + +#. module: base +#: model:res.company,overdue_msg:base.main_company +msgid "" +"Please note that the following payments are now due. If your payment " +" has been sent, kindly forward your payment details. If " +"payment will be delayed further, please contact us " +"to discuss. \n" +"Would your payment have been carried out after this mail was sent, please " +"consider the present one as void." +msgstr "" + +#. module: base +#: model:res.country,name:base.mx +msgid "Mexico" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_base_config_plugins +msgid "Plugins" +msgstr "" + +#. module: base +#: field:res.company,child_ids:0 +msgid "Child Companies" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_users +msgid "res.users" +msgstr "" + +#. module: base +#: model:res.country,name:base.ni +msgid "Nicaragua" +msgstr "" + +#. module: base +#: code:addons/orm.py:1046 +#, python-format +msgid "The write method is not implemented on this object !" +msgstr "" + +#. module: base +#: view:res.partner.event:0 +msgid "General Description" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_config_simple_view_form +#: view:res.config.view:0 +msgid "Configure Your Interface" +msgstr "" + +#. module: base +#: field:ir.values,meta:0 +msgid "Meta Datas" +msgstr "" + +#. module: base +#: sql_constraint:ir.ui.view_sc:0 +msgid "Shortcut for this menu already exists!" +msgstr "" + +#. module: base +#: model:res.country,name:base.ve +msgid "Venezuela" +msgstr "委內瑞拉" + +#. module: base +#: view:res.lang:0 +msgid "9. %j ==> 340" +msgstr "" + +#. module: base +#: model:res.country,name:base.zm +msgid "Zambia" +msgstr "贊比亞" + +#. module: base +#: help:res.partner,user_id:0 +msgid "" +"The internal user that is in charge of communicating with this partner if " +"any." +msgstr "" + +#. module: base +#: field:res.partner,parent_id:0 +msgid "Parent Partner" +msgstr "" + +#. module: base +#: view:ir.module.module:0 +msgid "Cancel Upgrade" +msgstr "" + +#. module: base +#: model:res.country,name:base.ci +msgid "Ivory Coast (Cote D'Ivoire)" +msgstr "科特迪瓦(象牙海岸)" + +#. module: base +#: model:res.country,name:base.kz +msgid "Kazakhstan" +msgstr "哈薩克" + +#. module: base +#: view:res.lang:0 +msgid "%w - Weekday number [0(Sunday),6]." +msgstr "" + +#. module: base +#: model:ir.actions.act_window,help:base.action_partner_form +msgid "" +"A customer is an entity you do business with, like a company or an " +"organization. A customer can have several contacts or addresses which are " +"the people working for this company. You can use the history tab, to follow " +"all transactions related to a customer: sales order, emails, opportunities, " +"claims, etc. If you use the email gateway, the Outlook or the Thunderbird " +"plugin, don't forget to register emails to each contact so that the gateway " +"will automatically attach incoming emails to the right partner." +msgstr "" + +#. module: base +#: field:ir.actions.report.xml,name:0 +#: field:ir.actions.todo,name:0 +#: field:ir.cron,name:0 +#: field:ir.model.access,name:0 +#: field:ir.model.fields,name:0 +#: field:ir.module.category,name:0 +#: field:ir.module.module,name:0 +#: field:ir.module.module.dependency,name:0 +#: report:ir.module.reference.graph:0 +#: field:ir.property,name:0 +#: field:ir.rule,name:0 +#: field:ir.sequence,name:0 +#: field:ir.sequence.type,name:0 +#: field:ir.values,name:0 +#: field:multi_company.default,name:0 +#: field:res.bank,name:0 +#: field:res.config.view,name:0 +#: field:res.lang,name:0 +#: field:res.partner,name:0 +#: field:res.partner.bank.type,name:0 +#: view:res.partner.event:0 +#: field:res.request.link,name:0 +#: field:workflow,name:0 +#: field:workflow.activity,name:0 +msgid "Name" +msgstr "" + +#. module: base +#: help:ir.actions.act_window,multi:0 +msgid "" +"If set to true, the action will not be displayed on the right toolbar of a " +"form view" +msgstr "" + +#. module: base +#: model:res.country,name:base.ms +msgid "Montserrat" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_model.py:205 +#, python-format +msgid "" +"The Selection Options expression is not a valid Pythonic expression.Please " +"provide an expression in the [('key','Label'), ...] format." +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_translation_app +msgid "Application Terms" +msgstr "" + +#. module: base +#: help:res.config.users,context_tz:0 +#: help:res.users,context_tz:0 +msgid "" +"The user's timezone, used to perform timezone conversions between the server " +"and the client." +msgstr "" + +#. module: base +#: field:ir.module.module,demo:0 +msgid "Demo data" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "English (UK)" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Japanese / 日本語" +msgstr "" + +#. module: base +#: help:workflow.transition,act_from:0 +msgid "" +"Source activity. When this activity is over, the condition is tested to " +"determine if we can start the ACT_TO activity." +msgstr "" + +#. module: base +#: model:res.partner.category,name:base.res_partner_category_3 +msgid "Starter Partner" +msgstr "" + +#. module: base +#: help:ir.model.fields,relation_field:0 +msgid "" +"For one2many fields, the field on the target model that implement the " +"opposite many2one relationship" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_actions_act_window_view +msgid "ir.actions.act_window.view" +msgstr "" + +#. module: base +#: report:ir.module.reference.graph:0 +msgid "Web" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "English (CA)" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_publisher_warranty_contract +msgid "publisher_warranty.contract" +msgstr "" + +#. module: base +#: model:res.country,name:base.et +msgid "Ethiopia" +msgstr "" + +#. module: base +#: help:res.country.state,code:0 +msgid "The state code in three chars.\n" +msgstr "" + +#. module: base +#: model:res.country,name:base.sj +msgid "Svalbard and Jan Mayen Islands" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_actions_wizard +#: selection:ir.ui.menu,action:0 +msgid "ir.actions.wizard" +msgstr "" + +#. module: base +#: view:ir.actions.act_window:0 +#: view:ir.actions.report.xml:0 +#: view:ir.actions.server:0 +#: view:ir.filters:0 +#: view:res.request:0 +msgid "Group By" +msgstr "" + +#. module: base +#: view:res.config:0 +#: view:res.config.installer:0 +msgid "title" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_base_language_install +msgid "Install Language" +msgstr "" + +#. module: base +#: view:ir.translation:0 +msgid "Translation" +msgstr "" + +#. module: base +#: selection:res.request,state:0 +msgid "closed" +msgstr "" + +#. module: base +#: selection:base.language.export,state:0 +msgid "get" +msgstr "" + +#. module: base +#: help:ir.model.fields,on_delete:0 +msgid "On delete property for many2one fields" +msgstr "" + +#. module: base +#: field:ir.actions.server,write_id:0 +msgid "Write Id" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_product +msgid "Products" +msgstr "" + +#. module: base +#: field:ir.actions.act_window,domain:0 +#: field:ir.filters,domain:0 +msgid "Domain Value" +msgstr "" + +#. module: base +#: view:ir.actions.server:0 +msgid "SMS Configuration" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Spanish (BO) / Español (BO)" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.ir_access_act +#: model:ir.ui.menu,name:base.menu_ir_access_act +msgid "Access Controls List" +msgstr "" + +#. module: base +#: model:res.country,name:base.um +msgid "USA Minor Outlying Islands" +msgstr "" + +#. module: base +#: field:res.partner.bank,state:0 +#: field:res.partner.bank.type.field,bank_type_id:0 +msgid "Bank Type" +msgstr "" + +#. module: base +#: code:addons/base/res/res_user.py:58 +#: code:addons/base/res/res_user.py:67 +#, python-format +msgid "The name of the group can not start with \"-\"" +msgstr "" + +#. module: base +#: view:ir.ui.view_sc:0 +#: field:res.partner.title,shortcut:0 +msgid "Shortcut" +msgstr "" + +#. module: base +#: field:ir.model.data,date_init:0 +msgid "Init Date" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Gujarati / ગુજરાતી" +msgstr "" + +#. module: base +#: code:addons/base/module/module.py:257 +#, python-format +msgid "" +"Unable to process module \"%s\" because an external dependency is not met: %s" +msgstr "" + +#. module: base +#: view:publisher_warranty.contract.wizard:0 +msgid "Please enter the serial key provided in your contract document:" +msgstr "" + +#. module: base +#: view:workflow.activity:0 +#: field:workflow.activity,flow_start:0 +msgid "Flow Start" +msgstr "" + +#. module: base +#: code:addons/__init__.py:834 +#, python-format +msgid "module base cannot be loaded! (hint: verify addons-path)" +msgstr "" + +#. module: base +#: view:res.partner.bank:0 +msgid "Bank Account Owner" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.act_values_form +msgid "Client Actions Connections" +msgstr "" + +#. module: base +#: field:ir.attachment,res_name:0 +#: field:ir.ui.view_sc,resource:0 +msgid "Resource Name" +msgstr "" + +#. module: base +#: selection:ir.cron,interval_type:0 +msgid "Hours" +msgstr "" + +#. module: base +#: model:res.country,name:base.gp +msgid "Guadeloupe (French)" +msgstr "" + +#. module: base +#: code:addons/base/res/res_lang.py:157 +#: code:addons/base/res/res_lang.py:159 +#: code:addons/base/res/res_lang.py:161 +#, python-format +msgid "User Error" +msgstr "" + +#. module: base +#: help:workflow.transition,signal:0 +msgid "" +"When the operation of transition comes from a button pressed in the client " +"form, signal tests the name of the pressed button. If signal is NULL, no " +"button is necessary to validate this transition." +msgstr "" + +#. module: base +#: help:multi_company.default,object_id:0 +msgid "Object affected by this rule" +msgstr "" + +#. module: base +#: report:ir.module.reference.graph:0 +msgid "Directory" +msgstr "" + +#. module: base +#: field:wizard.ir.model.menu.create,name:0 +msgid "Menu Name" +msgstr "" + +#. module: base +#: view:ir.module.module:0 +msgid "Author Website" +msgstr "" + +#. module: base +#: view:ir.attachment:0 +msgid "Month" +msgstr "" + +#. module: base +#: model:res.country,name:base.my +msgid "Malaysia" +msgstr "" + +#. module: base +#: view:base.language.install:0 +#: model:ir.actions.act_window,name:base.action_view_base_language_install +msgid "Load Official Translation" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_request_history +msgid "res.request.history" +msgstr "" + +#. module: base +#: view:ir.actions.server:0 +msgid "Client Action Configuration" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_partner_address +#: view:res.partner.address:0 +msgid "Partner Addresses" +msgstr "" + +#. module: base +#: help:ir.model.fields,translate:0 +msgid "" +"Whether values for this field can be translated (enables the translation " +"mechanism for that field)" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "%S - Seconds [00,61]." +msgstr "" + +#. module: base +#: model:res.country,name:base.cv +msgid "Cape Verde" +msgstr "" + +#. module: base +#: view:base.module.import:0 +msgid "Select module package to import (.zip file):" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.act_res_partner_event +#: field:res.partner,events:0 +#: field:res.partner.event,name:0 +#: model:res.widget,title:base.events_widget +msgid "Events" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_actions_url +#: selection:ir.ui.menu,action:0 +msgid "ir.actions.url" +msgstr "" + +#. module: base +#: model:res.widget,title:base.currency_converter_widget +msgid "Currency Converter" +msgstr "" + +#. module: base +#: code:addons/orm.py:156 +#, python-format +msgid "Wrong ID for the browse record, got %r, expected an integer." +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_partner_addess_tree +#: view:res.partner:0 +msgid "Partner Contacts" +msgstr "" + +#. module: base +#: field:base.module.update,add:0 +msgid "Number of modules added" +msgstr "" + +#. module: base +#: view:res.currency:0 +msgid "Price Accuracy" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Latvian / latviešu valoda" +msgstr "" + +#. module: base +#: view:res.config:0 +#: view:res.config.installer:0 +msgid "vsep" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "French / Français" +msgstr "" + +#. module: base +#: code:addons/orm.py:1049 +#, python-format +msgid "The create method is not implemented on this object !" +msgstr "" + +#. module: base +#: field:workflow.triggers,workitem_id:0 +msgid "Workitem" +msgstr "" + +#. module: base +#: view:ir.actions.todo:0 +msgid "Set as Todo" +msgstr "" + +#. module: base +#: field:ir.actions.act_window.view,act_window_id:0 +#: view:ir.actions.actions:0 +#: field:ir.actions.todo,action_id:0 +#: field:ir.ui.menu,action:0 +#: field:ir.values,action_id:0 +#: selection:ir.values,key:0 +#: view:res.users:0 +msgid "Action" +msgstr "" + +#. module: base +#: view:ir.actions.server:0 +msgid "Email Configuration" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_cron +msgid "ir.cron" +msgstr "" + +#. module: base +#: view:ir.rule:0 +msgid "Combination of rules" +msgstr "" + +#. module: base +#: view:ir.sequence:0 +msgid "Current Year without Century: %(y)s" +msgstr "" + +#. module: base +#: field:ir.actions.server,trigger_obj_id:0 +msgid "Trigger On" +msgstr "" + +#. module: base +#: sql_constraint:ir.rule:0 +msgid "Rule must have at least one checked access right !" +msgstr "" + +#. module: base +#: model:res.country,name:base.fj +msgid "Fiji" +msgstr "" + +#. module: base +#: field:ir.model.fields,size:0 +msgid "Size" +msgstr "" + +#. module: base +#: model:res.country,name:base.sd +msgid "Sudan" +msgstr "" + +#. module: base +#: model:res.country,name:base.fm +msgid "Micronesia" +msgstr "" + +#. module: base +#: view:res.request.history:0 +msgid "Request History" +msgstr "" + +#. module: base +#: field:ir.actions.act_window,menus:0 +#: field:ir.module.module,menus_by_module:0 +#: view:res.groups:0 +msgid "Menus" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Serbian (Latin) / srpski" +msgstr "" + +#. module: base +#: model:res.country,name:base.il +msgid "Israel" +msgstr "" + +#. module: base +#: model:ir.actions.wizard,name:base.wizard_server_action_create +msgid "Create Action" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_model_model +#: model:ir.model,name:base.model_ir_model +#: model:ir.ui.menu,name:base.ir_model_model_menu +msgid "Objects" +msgstr "" + +#. module: base +#: field:res.lang,time_format:0 +msgid "Time Format" +msgstr "" + +#. module: base +#: view:ir.module.module:0 +msgid "Defined Reports" +msgstr "" + +#. module: base +#: view:ir.actions.report.xml:0 +msgid "Report xml" +msgstr "" + +#. module: base +#: field:base.language.export,modules:0 +#: model:ir.actions.act_window,name:base.action_module_open_categ +#: model:ir.actions.act_window,name:base.open_module_tree +#: view:ir.module.module:0 +#: model:ir.ui.menu,name:base.menu_management +#: model:ir.ui.menu,name:base.menu_module_tree +msgid "Modules" +msgstr "" + +#. module: base +#: view:workflow.activity:0 +#: selection:workflow.activity,kind:0 +#: field:workflow.activity,subflow_id:0 +#: field:workflow.workitem,subflow_id:0 +msgid "Subflow" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_config +msgid "res.config" +msgstr "" + +#. module: base +#: field:workflow.transition,signal:0 +msgid "Signal (button Name)" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_res_bank_form +#: model:ir.ui.menu,name:base.menu_action_res_bank_form +#: view:res.bank:0 +#: field:res.partner,bank_ids:0 +msgid "Banks" +msgstr "" + +#. module: base +#: view:res.log:0 +msgid "Unread" +msgstr "" + +#. module: base +#: field:ir.cron,doall:0 +msgid "Repeat Missed" +msgstr "" + +#. module: base +#: help:ir.actions.server,state:0 +msgid "Type of the Action that is to be executed" +msgstr "" + +#. module: base +#: field:ir.server.object.lines,server_id:0 +msgid "Object Mapping" +msgstr "" + +#. module: base +#: help:res.currency,rate:0 +#: help:res.currency.rate,rate:0 +msgid "The rate of the currency to the currency of rate 1" +msgstr "" + +#. module: base +#: model:res.country,name:base.uk +msgid "United Kingdom" +msgstr "" + +#. module: base +#: view:res.config:0 +#: view:res.config.users:0 +#: view:res.config.view:0 +msgid "res_config_contents" +msgstr "" + +#. module: base +#: help:res.partner.category,active:0 +msgid "The active field allows you to hide the category without removing it." +msgstr "" + +#. module: base +#: report:ir.module.reference.graph:0 +msgid "Object:" +msgstr "" + +#. module: base +#: model:res.country,name:base.bw +msgid "Botswana" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_partner_title_partner +#: model:ir.ui.menu,name:base.menu_partner_title_partner +#: view:res.partner.title:0 +msgid "Partner Titles" +msgstr "" + +#. module: base +#: help:ir.actions.act_window,auto_refresh:0 +msgid "Add an auto-refresh on the view" +msgstr "" + +#. module: base +#: help:res.partner,employee:0 +msgid "Check this box if the partner is an Employee." +msgstr "" + +#. module: base +#: field:ir.actions.report.xml,report_rml_content:0 +#: field:ir.actions.report.xml,report_rml_content_data:0 +msgid "RML content" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_workflow_workitem_form +#: model:ir.ui.menu,name:base.menu_workflow_workitem +msgid "Workitems" +msgstr "" + +#. module: base +#: field:base.language.export,advice:0 +msgid "Advice" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_attachment +msgid "ir.attachment" +msgstr "" + +#. module: base +#: code:addons/orm.py:3533 +#, python-format +msgid "" +"You cannot perform this operation. New Record Creation is not allowed for " +"this object as this object is for reporting purpose." +msgstr "" + +#. module: base +#: view:base.language.import:0 +msgid "- module,type,name,res_id,src,value" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Lithuanian / Lietuvių kalba" +msgstr "" + +#. module: base +#: help:ir.actions.server,record_id:0 +msgid "" +"Provide the field name where the record id is stored after the create " +"operations. If it is empty, you can not track the new record." +msgstr "" + +#. module: base +#: help:ir.model.fields,relation:0 +msgid "For relationship fields, the technical name of the target model" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Indonesian / Bahasa Indonesia" +msgstr "" + +#. module: base +#: field:ir.ui.view,inherit_id:0 +msgid "Inherited View" +msgstr "" + +#. module: base +#: view:ir.translation:0 +msgid "Source Term" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_main_pm +msgid "Project" +msgstr "" + +#. module: base +#: field:ir.ui.menu,web_icon_hover_data:0 +msgid "Web Icon Image (hover)" +msgstr "" + +#. module: base +#: view:base.module.import:0 +msgid "Module file successfully imported!" +msgstr "" + +#. module: base +#: selection:ir.actions.todo,state:0 +msgid "Cancelled" +msgstr "" + +#. module: base +#: view:res.config.users:0 +msgid "Create User" +msgstr "" + +#. module: base +#: view:partner.clear.ids:0 +msgid "Want to Clear Ids ? " +msgstr "" + +#. module: base +#: field:publisher_warranty.contract,name:0 +#: field:publisher_warranty.contract.wizard,name:0 +msgid "Serial Key" +msgstr "" + +#. module: base +#: selection:res.request,priority:0 +msgid "Low" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_audit +msgid "Audit" +msgstr "" + +#. module: base +#: model:res.country,name:base.lc +msgid "Saint Lucia" +msgstr "" + +#. module: base +#: view:publisher_warranty.contract:0 +msgid "Maintenance Contract" +msgstr "" + +#. module: base +#: help:ir.actions.server,trigger_obj_id:0 +msgid "Select the object from the model on which the workflow will executed." +msgstr "" + +#. module: base +#: field:res.partner,employee:0 +msgid "Employee" +msgstr "" + +#. module: base +#: field:ir.model.access,perm_create:0 +msgid "Create Access" +msgstr "" + +#. module: base +#: field:res.partner.address,state_id:0 +msgid "Fed. State" +msgstr "" + +#. module: base +#: field:ir.actions.server,copy_object:0 +msgid "Copy Of" +msgstr "" + +#. module: base +#: field:ir.model,osv_memory:0 +msgid "In-memory model" +msgstr "" + +#. module: base +#: view:partner.clear.ids:0 +msgid "Clear Ids" +msgstr "" + +#. module: base +#: model:res.country,name:base.io +msgid "British Indian Ocean Territory" +msgstr "" + +#. module: base +#: field:res.config.users,view:0 +#: field:res.config.view,view:0 +#: field:res.users,view:0 +msgid "Interface" +msgstr "" + +#. module: base +#: view:ir.actions.server:0 +msgid "Field Mapping" +msgstr "" + +#. module: base +#: view:publisher_warranty.contract:0 +msgid "Refresh Validation Dates" +msgstr "" + +#. module: base +#: view:ir.model:0 +#: field:ir.model.fields,ttype:0 +msgid "Field Type" +msgstr "" + +#. module: base +#: field:res.country.state,code:0 +msgid "State Code" +msgstr "" + +#. module: base +#: field:ir.model.fields,on_delete:0 +msgid "On delete" +msgstr "" + +#. module: base +#: selection:res.lang,direction:0 +msgid "Left-to-Right" +msgstr "" + +#. module: base +#: view:res.lang:0 +#: field:res.lang,translatable:0 +msgid "Translatable" +msgstr "" + +#. module: base +#: model:res.country,name:base.vn +msgid "Vietnam" +msgstr "" + +#. module: base +#: field:res.config.users,signature:0 +#: view:res.users:0 +#: field:res.users,signature:0 +msgid "Signature" +msgstr "" + +#. module: base +#: code:addons/fields.py:456 +#: code:addons/fields.py:654 +#: code:addons/fields.py:656 +#: code:addons/fields.py:658 +#: code:addons/fields.py:660 +#: code:addons/fields.py:662 +#: code:addons/fields.py:664 +#, python-format +msgid "Not Implemented" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_widget_user +msgid "res.widget.user" +msgstr "" + +#. module: base +#: field:res.partner.category,complete_name:0 +msgid "Full Name" +msgstr "" + +#. module: base +#: view:base.module.configuration:0 +msgid "_Ok" +msgstr "" + +#. module: base +#: help:ir.filters,user_id:0 +msgid "False means for every user" +msgstr "" + +#. module: base +#: code:addons/base/module/module.py:198 +#, python-format +msgid "The name of the module must be unique !" +msgstr "" + +#. module: base +#: model:res.country,name:base.mz +msgid "Mozambique" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_project_long_term +msgid "Long Term Planning" +msgstr "" + +#. module: base +#: field:ir.actions.server,message:0 +#: view:partner.sms.send:0 +#: field:partner.wizard.spam,text:0 +#: field:res.log,name:0 +msgid "Message" +msgstr "" + +#. module: base +#: field:ir.actions.act_window.view,multi:0 +msgid "On Multiple Doc." +msgstr "" + +#. module: base +#: view:res.partner:0 +#: field:res.partner,user_id:0 +msgid "Salesman" +msgstr "" + +#. module: base +#: field:res.partner,address:0 +#: view:res.partner.address:0 +msgid "Contacts" +msgstr "" + +#. module: base +#: code:addons/orm.py:3199 +#, python-format +msgid "" +"Unable to delete this document because it is used as a default property" +msgstr "" + +#. module: base +#: view:res.widget.wizard:0 +msgid "Add" +msgstr "" + +#. module: base +#: view:base.module.upgrade:0 +#: model:ir.actions.act_window,name:base.action_view_base_module_upgrade_window +#: model:ir.ui.menu,name:base.menu_view_base_module_upgrade +msgid "Apply Scheduled Upgrades" +msgstr "" + +#. module: base +#: view:res.widget:0 +msgid "Widgets" +msgstr "" + +#. module: base +#: model:res.country,name:base.cz +msgid "Czech Republic" +msgstr "" + +#. module: base +#: view:res.widget.wizard:0 +msgid "Widget Wizard" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,help:base.act_ir_actions_todo_form +msgid "" +"The configuration wizards are used to help you configure a new instance of " +"OpenERP. They are launched during the installation of new modules, but you " +"can choose to restart some wizards manually from this menu." +msgstr "" + +#. module: base +#: code:addons/base/res/res_user.py:206 +#, python-format +msgid "" +"Please use the change password wizard (in User Preferences or User menu) to " +"change your own password." +msgstr "" + +#. module: base +#: code:addons/orm.py:1350 +#, python-format +msgid "Insufficient fields for Calendar View!" +msgstr "" + +#. module: base +#: selection:ir.property,type:0 +msgid "Integer" +msgstr "" + +#. module: base +#: help:ir.actions.report.xml,report_rml:0 +msgid "" +"The path to the main report file (depending on Report Type) or NULL if the " +"content is in another data field" +msgstr "" + +#. module: base +#: help:res.config.users,company_id:0 +#: help:res.users,company_id:0 +msgid "The company this user is currently working for." +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_wizard_ir_model_menu_create +msgid "wizard.ir.model.menu.create" +msgstr "" + +#. module: base +#: view:workflow.transition:0 +msgid "Transition" +msgstr "" + +#. module: base +#: field:res.groups,menu_access:0 +msgid "Access Menu" +msgstr "" + +#. module: base +#: model:res.country,name:base.na +msgid "Namibia" +msgstr "" + +#. module: base +#: model:res.country,name:base.mn +msgid "Mongolia" +msgstr "" + +#. module: base +#: view:ir.module.module:0 +msgid "Created Menus" +msgstr "" + +#. module: base +#: selection:ir.ui.view,type:0 +msgid "mdx" +msgstr "" + +#. module: base +#: model:res.country,name:base.bi +msgid "Burundi" +msgstr "" + +#. module: base +#: view:base.language.install:0 +#: view:base.module.import:0 +#: view:base.module.update:0 +#: view:publisher_warranty.contract.wizard:0 +#: view:res.request:0 +#: wizard_button:server.action.create,init,end:0 +#: wizard_button:server.action.create,step_1,end:0 +msgid "Close" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Spanish (MX) / Español (MX)" +msgstr "" + +#. module: base +#: view:res.log:0 +msgid "My Logs" +msgstr "" + +#. module: base +#: model:res.country,name:base.bt +msgid "Bhutan" +msgstr "" + +#. module: base +#: help:ir.sequence,number_next:0 +msgid "Next number of this sequence" +msgstr "" + +#. module: base +#: model:res.partner.category,name:base.res_partner_category_11 +msgid "Textile Suppliers" +msgstr "" + +#. module: base +#: selection:ir.actions.url,target:0 +msgid "This Window" +msgstr "" + +#. module: base +#: view:publisher_warranty.contract:0 +msgid "Publisher Warranty Contracts" +msgstr "" + +#. module: base +#: help:res.log,name:0 +msgid "The logging message." +msgstr "" + +#. module: base +#: field:base.language.export,format:0 +msgid "File Format" +msgstr "" + +#. module: base +#: field:res.lang,iso_code:0 +msgid "ISO code" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_config_view +msgid "res.config.view" +msgstr "" + +#. module: base +#: view:res.log:0 +#: field:res.log,read:0 +msgid "Read" +msgstr "" + +#. module: base +#: sql_constraint:res.country:0 +msgid "The name of the country must be unique !" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,help:base.action_country_state +msgid "" +"If you are working on the American market, you can manage the different " +"federal states you are working on from here. Each state is attached to one " +"country." +msgstr "" + +#. module: base +#: view:workflow.workitem:0 +msgid "Workflow Workitems" +msgstr "" + +#. module: base +#: model:res.country,name:base.vc +msgid "Saint Vincent & Grenadines" +msgstr "" + +#. module: base +#: field:partner.sms.send,password:0 +#: field:res.config.users,password:0 +#: field:res.users,password:0 +msgid "Password" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_model_fields +#: view:ir.model:0 +#: field:ir.model,field_id:0 +#: model:ir.model,name:base.model_ir_model_fields +#: view:ir.model.fields:0 +#: model:ir.ui.menu,name:base.ir_model_model_fields +msgid "Fields" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_partner_employee_form +msgid "Employees" +msgstr "" + +#. module: base +#: help:res.log,read:0 +msgid "" +"If this log item has been read, get() should not send it to the client" +msgstr "" + +#. module: base +#: field:res.company,rml_header2:0 +#: field:res.company,rml_header3:0 +msgid "RML Internal Header" +msgstr "" + +#. module: base +#: field:ir.actions.act_window,search_view_id:0 +msgid "Search View Ref." +msgstr "" + +#. module: base +#: field:ir.module.module,installed_version:0 +msgid "Latest version" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,help:base.res_partner_canal-act +msgid "" +"Track from where is coming your leads and opportunities by creating specific " +"channels that will be maintained at the creation of a document in the " +"system. Some examples of channels can be: Website, Phone Call, Reseller, etc." +msgstr "" + +#. module: base +#: model:res.partner.bank.type.field,name:base.bank_normal_field +msgid "acc_number" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_partner_address_form +#: model:ir.ui.menu,name:base.menu_partner_address_form +msgid "Addresses" +msgstr "" + +#. module: base +#: model:res.country,name:base.mm +msgid "Myanmar" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Chinese (CN) / 简体中文" +msgstr "" + +#. module: base +#: field:res.bank,street:0 +#: field:res.partner.address,street:0 +#: field:res.partner.bank,street:0 +msgid "Street" +msgstr "" + +#. module: base +#: model:res.country,name:base.yu +msgid "Yugoslavia" +msgstr "" + +#. module: base +#: field:ir.model.data,name:0 +msgid "XML Identifier" +msgstr "" + +#. module: base +#: model:res.country,name:base.ca +msgid "Canada" +msgstr "" + +#. module: base +#: selection:ir.module.module.dependency,state:0 +msgid "Unknown" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_res_users_my +msgid "Change My Preferences" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_actions.py:164 +#, python-format +msgid "Invalid model name in the action definition." +msgstr "" + +#. module: base +#: field:partner.sms.send,text:0 +msgid "SMS Message" +msgstr "" + +#. module: base +#: model:res.country,name:base.cm +msgid "Cameroon" +msgstr "" + +#. module: base +#: model:res.country,name:base.bf +msgid "Burkina Faso" +msgstr "" + +#. module: base +#: selection:ir.actions.todo,state:0 +msgid "Skipped" +msgstr "" + +#. module: base +#: selection:ir.model.fields,state:0 +msgid "Custom Field" +msgstr "" + +#. module: base +#: field:ir.module.module,web:0 +msgid "Has a web component" +msgstr "" + +#. module: base +#: model:res.country,name:base.cc +msgid "Cocos (Keeling) Islands" +msgstr "" + +#. module: base +#: selection:base.language.install,state:0 +#: selection:base.module.import,state:0 +#: selection:base.module.update,state:0 +msgid "init" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "11. %U or %W ==> 48 (49th week)" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_partner_bank_type_field +msgid "Bank type fields" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Dutch / Nederlands" +msgstr "" + +#. module: base +#: code:addons/base/res/res_config.py:384 +#, python-format +msgid "" +"\n" +"\n" +"This addon is already installed on your system" +msgstr "" + +#. module: base +#: help:ir.cron,interval_number:0 +msgid "Repeat every x." +msgstr "" + +#. module: base +#: wizard_view:server.action.create,step_1:0 +#: wizard_field:server.action.create,step_1,report:0 +msgid "Select Report" +msgstr "" + +#. module: base +#: report:ir.module.reference.graph:0 +msgid "1cm 28cm 20cm 28cm" +msgstr "" + +#. module: base +#: field:ir.module.module,maintainer:0 +msgid "Maintainer" +msgstr "" + +#. module: base +#: field:ir.sequence,suffix:0 +msgid "Suffix" +msgstr "" + +#. module: base +#: model:res.country,name:base.mo +msgid "Macau" +msgstr "" + +#. module: base +#: model:ir.actions.report.xml,name:base.res_partner_address_report +msgid "Labels" +msgstr "" + +#. module: base +#: field:partner.wizard.spam,email_from:0 +msgid "Sender's email" +msgstr "" + +#. module: base +#: field:ir.default,field_name:0 +msgid "Object Field" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Spanish (PE) / Español (PE)" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "French (CH) / Français (CH)" +msgstr "" + +#. module: base +#: help:res.config.users,action_id:0 +#: help:res.users,action_id:0 +msgid "" +"If specified, this action will be opened at logon for this user, in addition " +"to the standard menu." +msgstr "" + +#. module: base +#: view:ir.values:0 +msgid "Client Actions" +msgstr "" + +#. module: base +#: code:addons/orm.py:1806 +#, python-format +msgid "The exists method is not implemented on this object !" +msgstr "" + +#. module: base +#: code:addons/base/module/module.py:336 +#, python-format +msgid "" +"You try to upgrade a module that depends on the module: %s.\n" +"But this module is not available in your system." +msgstr "" + +#. module: base +#: field:workflow.transition,act_to:0 +msgid "Destination Activity" +msgstr "" + +#. module: base +#: view:ir.values:0 +msgid "Connect Events to Actions" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_base_update_translations +msgid "base.update.translations" +msgstr "" + +#. module: base +#: field:ir.module.category,parent_id:0 +#: field:res.partner.category,parent_id:0 +msgid "Parent Category" +msgstr "" + +#. module: base +#: selection:ir.property,type:0 +msgid "Integer Big" +msgstr "" + +#. module: base +#: selection:res.partner.address,type:0 +#: selection:res.partner.title,domain:0 +#: view:res.users:0 +msgid "Contact" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_ui_menu +msgid "ir.ui.menu" +msgstr "" + +#. module: base +#: model:res.country,name:base.us +msgid "United States" +msgstr "" + +#. module: base +#: view:ir.module.module:0 +msgid "Cancel Uninstall" +msgstr "" + +#. module: base +#: view:res.bank:0 +#: view:res.partner:0 +#: view:res.partner.address:0 +msgid "Communication" +msgstr "" + +#. module: base +#: view:ir.actions.report.xml:0 +msgid "RML Report" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_server_object_lines +msgid "ir.server.object.lines" +msgstr "" + +#. module: base +#: code:addons/base/module/module.py:531 +#, python-format +msgid "Module %s: Invalid Quality Certificate" +msgstr "" + +#. module: base +#: model:res.country,name:base.kw +msgid "Kuwait" +msgstr "" + +#. module: base +#: field:workflow.workitem,inst_id:0 +msgid "Instance" +msgstr "" + +#. module: base +#: help:ir.actions.report.xml,attachment:0 +msgid "" +"This is the filename of the attachment used to store the printing result. " +"Keep empty to not save the printed reports. You can use a python expression " +"with the object and time variables." +msgstr "" + +#. module: base +#: selection:ir.property,type:0 +msgid "Many2One" +msgstr "" + +#. module: base +#: model:res.country,name:base.ng +msgid "Nigeria" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_model.py:250 +#, python-format +msgid "For selection fields, the Selection Options must be given!" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_partner_sms_send +msgid "SMS Send" +msgstr "" + +#. module: base +#: field:res.company,user_ids:0 +msgid "Accepted Users" +msgstr "" + +#. module: base +#: field:ir.ui.menu,web_icon_data:0 +msgid "Web Icon Image" +msgstr "" + +#. module: base +#: view:ir.values:0 +msgid "Values for Event Type" +msgstr "" + +#. module: base +#: selection:ir.model.fields,select_level:0 +msgid "Always Searchable" +msgstr "" + +#. module: base +#: model:res.country,name:base.hk +msgid "Hong Kong" +msgstr "" + +#. module: base +#: help:ir.actions.server,name:0 +msgid "Easy to Refer action by name e.g. One Sales Order -> Many Invoices" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,help:base.action_partner_address_form +msgid "" +"Customers (also called Partners in other areas of the system) helps you " +"manage your address book of companies whether they are prospects, customers " +"and/or suppliers. The partner form allows you to track and record all the " +"necessary information to interact with your partners from the company " +"address to their contacts as well as pricelists, and much more. If you " +"installed the CRM, with the history tab, you can track all the interactions " +"with a partner such as opportunities, emails, or sales orders issued." +msgstr "" + +#. module: base +#: model:res.country,name:base.ph +msgid "Philippines" +msgstr "" + +#. module: base +#: model:res.country,name:base.ma +msgid "Morocco" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "2. %a ,%A ==> Fri, Friday" +msgstr "" + +#. module: base +#: field:res.widget,content:0 +msgid "Content" +msgstr "" + +#. module: base +#: help:ir.rule,global:0 +msgid "If no group is specified the rule is global and applied to everyone" +msgstr "" + +#. module: base +#: model:res.country,name:base.td +msgid "Chad" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_workflow_transition +msgid "workflow.transition" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "%a - Abbreviated weekday name." +msgstr "" + +#. module: base +#: report:ir.module.reference.graph:0 +msgid "Introspection report on objects" +msgstr "" + +#. module: base +#: model:res.country,name:base.pf +msgid "Polynesia (French)" +msgstr "" + +#. module: base +#: model:res.country,name:base.dm +msgid "Dominica" +msgstr "" + +#. module: base +#: sql_constraint:publisher_warranty.contract:0 +msgid "" +"Your publisher warranty contract is already subscribed in the system !" +msgstr "" + +#. module: base +#: help:ir.cron,nextcall:0 +msgid "Next planned execution date for this scheduler" +msgstr "" + +#. module: base +#: help:res.config.users,view:0 +#: help:res.users,view:0 +msgid "Choose between the simplified interface and the extended one" +msgstr "" + +#. module: base +#: model:res.country,name:base.np +msgid "Nepal" +msgstr "" + +#. module: base +#: code:addons/orm.py:2307 +#, python-format +msgid "" +"Invalid value for reference field \"%s\" (last part must be a non-zero " +"integer): \"%s\"" +msgstr "" + +#. module: base +#: help:ir.cron,args:0 +msgid "Arguments to be passed to the method. e.g. (uid,)" +msgstr "" + +#. module: base +#: help:ir.ui.menu,groups_id:0 +msgid "" +"If you have groups, the visibility of this menu will be based on these " +"groups. If this field is empty, OpenERP will compute visibility based on the " +"related object's read access." +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_ui_view_custom +#: model:ir.ui.menu,name:base.menu_action_ui_view_custom +#: view:ir.ui.view.custom:0 +msgid "Customized Views" +msgstr "" + +#. module: base +#: view:partner.sms.send:0 +msgid "Bulk SMS send" +msgstr "" + +#. module: base +#: view:ir.sequence:0 +msgid "Seconde: %(sec)s" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_view_base_module_update +msgid "Update Modules List" +msgstr "" + +#. module: base +#: code:addons/base/module/module.py:255 +#, python-format +msgid "" +"Unable to upgrade module \"%s\" because an external dependency is not met: %s" +msgstr "" + +#. module: base +#: code:addons/base/res/res_user.py:257 +#, python-format +msgid "" +"Please keep in mind that documents currently displayed may not be relevant " +"after switching to another company. If you have unsaved changes, please make " +"sure to save and close all forms before switching to a different company. " +"(You can click on Cancel in the User Preferences now)" +msgstr "" + +#. module: base +#: view:ir.actions.configuration.wizard:0 +msgid "Continue" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Thai / ภาษาไทย" +msgstr "" + +#. module: base +#: code:addons/orm.py:158 +#, python-format +msgid "Object %s does not exists" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Slovenian / slovenščina" +msgstr "" + +#. module: base +#: field:ir.actions.report.xml,attachment_use:0 +msgid "Reload from Attachment" +msgstr "" + +#. module: base +#: model:res.country,name:base.bv +msgid "Bouvet Island" +msgstr "" + +#. module: base +#: field:ir.attachment,name:0 +msgid "Attachment Name" +msgstr "" + +#. module: base +#: field:base.language.export,data:0 +#: field:base.language.import,data:0 +msgid "File" +msgstr "" + +#. module: base +#: view:res.config.users:0 +msgid "Add User" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_view_base_module_upgrade_install +msgid "Module Upgrade Install" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_actions_configuration_wizard +msgid "ir.actions.configuration.wizard" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "%b - Abbreviated month name." +msgstr "" + +#. module: base +#: field:res.partner,supplier:0 +#: view:res.partner.address:0 +#: field:res.partner.address,is_supplier_add:0 +#: model:res.partner.category,name:base.res_partner_category_8 +msgid "Supplier" +msgstr "" + +#. module: base +#: view:ir.actions.server:0 +#: selection:ir.actions.server,state:0 +msgid "Multi Actions" +msgstr "" + +#. module: base +#: view:base.language.export:0 +#: view:base.language.import:0 +#: view:wizard.ir.model.menu.create:0 +msgid "_Close" +msgstr "" + +#. module: base +#: field:multi_company.default,company_dest_id:0 +msgid "Default Company" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Spanish (EC) / Español (EC)" +msgstr "" + +#. module: base +#: help:ir.ui.view,xml_id:0 +msgid "ID of the view defined in xml file" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_base_module_import +#: model:ir.ui.menu,name:base.menu_view_base_module_import +msgid "Import Module" +msgstr "" + +#. module: base +#: model:res.country,name:base.as +msgid "American Samoa" +msgstr "" + +#. module: base +#: help:ir.actions.act_window,res_model:0 +msgid "Model name of the object to open in the view window" +msgstr "" + +#. module: base +#: field:res.log,secondary:0 +msgid "Secondary Log" +msgstr "" + +#. module: base +#: field:ir.model.fields,selectable:0 +msgid "Selectable" +msgstr "" + +#. module: base +#: view:res.request.link:0 +msgid "Request Link" +msgstr "" + +#. module: base +#: view:ir.attachment:0 +#: selection:ir.attachment,type:0 +#: field:ir.module.module,url:0 +msgid "URL" +msgstr "" + +#. module: base +#: help:res.country,name:0 +msgid "The full name of the country." +msgstr "" + +#. module: base +#: selection:ir.actions.server,state:0 +msgid "Iteration" +msgstr "" + +#. module: base +#: code:addons/orm.py:3448 +#: code:addons/orm.py:3532 +#, python-format +msgid "UserError" +msgstr "" + +#. module: base +#: model:res.country,name:base.ae +msgid "United Arab Emirates" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_crm_case_job_req_main +msgid "Recruitment" +msgstr "" + +#. module: base +#: model:res.country,name:base.re +msgid "Reunion (French)" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_model.py:321 +#, python-format +msgid "" +"New column name must still start with x_ , because it is a custom field!" +msgstr "" + +#. module: base +#: view:ir.model.access:0 +#: view:ir.rule:0 +#: field:ir.rule,global:0 +msgid "Global" +msgstr "" + +#. module: base +#: model:res.country,name:base.mp +msgid "Northern Mariana Islands" +msgstr "" + +#. module: base +#: model:res.country,name:base.sb +msgid "Solomon Islands" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_model.py:490 +#: code:addons/orm.py:1897 +#: code:addons/orm.py:2972 +#: code:addons/orm.py:3165 +#: code:addons/orm.py:3365 +#: code:addons/orm.py:3817 +#, python-format +msgid "AccessError" +msgstr "" + +#. module: base +#: view:res.request:0 +msgid "Waiting" +msgstr "" + +#. module: base +#: code:addons/__init__.py:834 +#, python-format +msgid "Could not load base module" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "8. %I:%M:%S %p ==> 06:25:20 PM" +msgstr "" + +#. module: base +#: code:addons/orm.py:1803 +#, python-format +msgid "The copy method is not implemented on this object !" +msgstr "" + +#. module: base +#: field:res.log,create_date:0 +msgid "Creation Date" +msgstr "" + +#. module: base +#: view:ir.translation:0 +#: model:ir.ui.menu,name:base.menu_translation +msgid "Translations" +msgstr "" + +#. module: base +#: field:ir.sequence,padding:0 +msgid "Number padding" +msgstr "" + +#. module: base +#: view:ir.actions.report.xml:0 +msgid "Report" +msgstr "" + +#. module: base +#: model:res.country,name:base.ua +msgid "Ukraine" +msgstr "" + +#. module: base +#: model:res.country,name:base.to +msgid "Tonga" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_module_category +#: view:ir.module.category:0 +msgid "Module Category" +msgstr "" + +#. module: base +#: view:partner.wizard.ean.check:0 +msgid "Ignore" +msgstr "" + +#. module: base +#: report:ir.module.reference.graph:0 +msgid "Reference Guide" +msgstr "" + +#. module: base +#: view:ir.ui.view:0 +msgid "Architecture" +msgstr "" + +#. module: base +#: model:res.country,name:base.ml +msgid "Mali" +msgstr "" + +#. module: base +#: help:res.config.users,email:0 +#: help:res.users,email:0 +msgid "" +"If an email is provided, the user will be sent a message welcoming him.\n" +"\n" +"Warning: if \"email_from\" and \"smtp_server\" aren't configured, it won't " +"be possible to email new users." +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Flemish (BE) / Vlaams (BE)" +msgstr "" + +#. module: base +#: field:ir.cron,interval_number:0 +msgid "Interval Number" +msgstr "" + +#. module: base +#: model:res.country,name:base.tk +msgid "Tokelau" +msgstr "" + +#. module: base +#: field:ir.actions.report.xml,report_xsl:0 +msgid "XSL path" +msgstr "" + +#. module: base +#: model:res.country,name:base.bn +msgid "Brunei Darussalam" +msgstr "" + +#. module: base +#: view:ir.actions.act_window:0 +#: field:ir.actions.act_window,view_type:0 +#: field:ir.actions.act_window.view,view_mode:0 +#: field:ir.ui.view,type:0 +#: field:wizard.ir.model.menu.create.line,view_type:0 +msgid "View Type" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.next_id_2 +msgid "User Interface" +msgstr "" + +#. module: base +#: field:ir.attachment,create_date:0 +msgid "Date Created" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_actions_todo +msgid "ir.actions.todo" +msgstr "" + +#. module: base +#: code:addons/base/res/res_config.py:94 +#, python-format +msgid "Couldn't find previous ir.actions.todo" +msgstr "" + +#. module: base +#: view:ir.actions.act_window:0 +msgid "General Settings" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_administration_shortcut +msgid "Custom Shortcuts" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Vietnamese / Tiếng Việt" +msgstr "" + +#. module: base +#: model:res.country,name:base.dz +msgid "Algeria" +msgstr "" + +#. module: base +#: model:res.country,name:base.be +msgid "Belgium" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_osv_memory_autovacuum +msgid "osv_memory.autovacuum" +msgstr "" + +#. module: base +#: field:base.language.export,lang:0 +#: field:base.language.install,lang:0 +#: field:base.update.translations,lang:0 +#: field:ir.translation,lang:0 +#: field:res.config.users,context_lang:0 +#: field:res.partner,lang:0 +#: field:res.users,context_lang:0 +msgid "Language" +msgstr "" + +#. module: base +#: model:res.country,name:base.gm +msgid "Gambia" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_res_company_form +#: model:ir.model,name:base.model_res_company +#: model:ir.ui.menu,name:base.menu_action_res_company_form +#: model:ir.ui.menu,name:base.menu_res_company_global +#: view:res.company:0 +#: field:res.config.users,company_ids:0 +#: view:res.users:0 +#: field:res.users,company_ids:0 +msgid "Companies" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "%H - Hour (24-hour clock) [00,23]." +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_widget +msgid "res.widget" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_model.py:258 +#, python-format +msgid "Model %s does not exist!" +msgstr "" + +#. module: base +#: code:addons/base/res/res_lang.py:159 +#, python-format +msgid "You cannot delete the language which is User's Preferred Language !" +msgstr "" + +#. module: base +#: code:addons/fields.py:103 +#, python-format +msgid "Not implemented get_memory method !" +msgstr "" + +#. module: base +#: view:ir.actions.server:0 +#: field:ir.actions.server,code:0 +#: selection:ir.actions.server,state:0 +msgid "Python Code" +msgstr "" + +#. module: base +#: code:addons/base/module/wizard/base_module_import.py:67 +#, python-format +msgid "Can not create the module file: %s !" +msgstr "" + +#. module: base +#: model:ir.module.module,description:base.module_meta_information +msgid "The kernel of OpenERP, needed for all installation." +msgstr "" + +#. module: base +#: view:base.language.install:0 +#: view:base.module.import:0 +#: view:base.module.update:0 +#: view:base.module.upgrade:0 +#: view:base.update.translations:0 +#: view:partner.clear.ids:0 +#: view:partner.sms.send:0 +#: view:partner.wizard.spam:0 +#: view:publisher_warranty.contract.wizard:0 +#: view:res.widget.wizard:0 +msgid "Cancel" +msgstr "" + +#. module: base +#: selection:base.language.export,format:0 +msgid "PO File" +msgstr "" + +#. module: base +#: model:res.country,name:base.nt +msgid "Neutral Zone" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Hindi / हिंदी" +msgstr "" + +#. module: base +#: view:ir.model:0 +msgid "Custom" +msgstr "" + +#. module: base +#: view:res.request:0 +msgid "Current" +msgstr "" + +#. module: base +#: model:res.partner.category,name:base.res_partner_category_9 +msgid "Components Supplier" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_res_users +#: field:ir.default,uid:0 +#: model:ir.ui.menu,name:base.menu_action_res_users +#: model:ir.ui.menu,name:base.menu_users +#: view:res.groups:0 +#: field:res.groups,users:0 +#: view:res.users:0 +msgid "Users" +msgstr "" + +#. module: base +#: field:ir.module.module,published_version:0 +msgid "Published Version" +msgstr "" + +#. module: base +#: model:res.country,name:base.is +msgid "Iceland" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.ir_action_window +#: model:ir.ui.menu,name:base.menu_ir_action_window +msgid "Window Actions" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "%I - Hour (12-hour clock) [01,12]." +msgstr "" + +#. module: base +#: selection:publisher_warranty.contract.wizard,state:0 +msgid "Finished" +msgstr "" + +#. module: base +#: model:res.country,name:base.de +msgid "Germany" +msgstr "" + +#. module: base +#: view:ir.sequence:0 +msgid "Week of the year: %(woy)s" +msgstr "" + +#. module: base +#: model:res.partner.category,name:base.res_partner_category_14 +msgid "Bad customers" +msgstr "" + +#. module: base +#: report:ir.module.reference.graph:0 +msgid "Reports :" +msgstr "" + +#. module: base +#: model:res.country,name:base.gy +msgid "Guyana" +msgstr "" + +#. module: base +#: help:ir.actions.act_window,view_type:0 +msgid "" +"View type: set to 'tree' for a hierarchical tree view, or 'form' for other " +"views" +msgstr "" + +#. module: base +#: code:addons/base/res/res_config.py:421 +#, python-format +msgid "Click 'Continue' to configure the next addon..." +msgstr "" + +#. module: base +#: field:ir.actions.server,record_id:0 +msgid "Create Id" +msgstr "" + +#. module: base +#: model:res.country,name:base.hn +msgid "Honduras" +msgstr "" + +#. module: base +#: help:res.config.users,menu_tips:0 +#: help:res.users,menu_tips:0 +msgid "" +"Check out this box if you want to always display tips on each menu action" +msgstr "" + +#. module: base +#: model:res.country,name:base.eg +msgid "Egypt" +msgstr "" + +#. module: base +#: field:ir.rule,perm_read:0 +msgid "Apply For Read" +msgstr "" + +#. module: base +#: help:ir.actions.server,model_id:0 +msgid "" +"Select the object on which the action will work (read, write, create)." +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_actions.py:629 +#, python-format +msgid "Please specify server option --email-from !" +msgstr "" + +#. module: base +#: field:base.language.import,name:0 +msgid "Language Name" +msgstr "" + +#. module: base +#: selection:ir.property,type:0 +msgid "Boolean" +msgstr "" + +#. module: base +#: view:ir.model:0 +msgid "Fields Description" +msgstr "" + +#. module: base +#: view:ir.attachment:0 +#: view:ir.cron:0 +#: view:ir.model.access:0 +#: view:ir.model.data:0 +#: view:ir.model.fields:0 +#: view:ir.module.module:0 +#: view:ir.rule:0 +#: view:ir.ui.view:0 +#: view:ir.values:0 +#: view:res.partner:0 +#: view:res.partner.address:0 +#: view:workflow.activity:0 +msgid "Group By..." +msgstr "" + +#. module: base +#: view:ir.model.fields:0 +#: field:ir.model.fields,readonly:0 +#: field:res.partner.bank.type.field,readonly:0 +msgid "Readonly" +msgstr "" + +#. module: base +#: field:ir.actions.act_window.view,view_id:0 +#: field:ir.default,page:0 +#: selection:ir.translation,type:0 +#: field:wizard.ir.model.menu.create.line,view_id:0 +msgid "View" +msgstr "" + +#. module: base +#: selection:ir.module.module,state:0 +#: selection:ir.module.module.dependency,state:0 +msgid "To be installed" +msgstr "" + +#. module: base +#: help:ir.actions.act_window,display_menu_tip:0 +msgid "" +"It gives the status if the tip has to be displayed or not when a user " +"executes an action" +msgstr "" + +#. module: base +#: view:ir.model:0 +#: model:ir.module.module,shortdesc:base.module_meta_information +#: field:res.currency,base:0 +msgid "Base" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Telugu / తెలుగు" +msgstr "" + +#. module: base +#: model:res.country,name:base.lr +msgid "Liberia" +msgstr "" + +#. module: base +#: view:ir.attachment:0 +#: view:ir.model:0 +#: view:res.groups:0 +#: view:res.partner:0 +#: field:res.partner,comment:0 +#: model:res.widget,title:base.note_widget +msgid "Notes" +msgstr "" + +#. module: base +#: field:ir.config_parameter,value:0 +#: field:ir.property,value_binary:0 +#: field:ir.property,value_datetime:0 +#: field:ir.property,value_float:0 +#: field:ir.property,value_integer:0 +#: field:ir.property,value_reference:0 +#: field:ir.property,value_text:0 +#: selection:ir.server.object.lines,type:0 +#: field:ir.server.object.lines,value:0 +#: view:ir.values:0 +#: field:ir.values,value:0 +#: field:ir.values,value_unpickle:0 +msgid "Value" +msgstr "" + +#. module: base +#: field:ir.sequence,code:0 +#: field:ir.sequence.type,code:0 +#: selection:ir.translation,type:0 +#: field:res.bank,code:0 +#: field:res.partner.bank.type,code:0 +msgid "Code" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_config_installer +msgid "res.config.installer" +msgstr "" + +#. module: base +#: model:res.country,name:base.mc +msgid "Monaco" +msgstr "" + +#. module: base +#: selection:ir.cron,interval_type:0 +msgid "Minutes" +msgstr "" + +#. module: base +#: selection:ir.translation,type:0 +msgid "Help" +msgstr "" + +#. module: base +#: help:res.config.users,menu_id:0 +#: help:res.users,menu_id:0 +msgid "" +"If specified, the action will replace the standard menu for this user." +msgstr "" + +#. module: base +#: selection:ir.actions.server,state:0 +msgid "Write Object" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_fundrising +msgid "Fund Raising" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.ir_sequence_type +#: model:ir.ui.menu,name:base.menu_ir_sequence_type +msgid "Sequence Codes" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Spanish (CO) / Español (CO)" +msgstr "" + +#. module: base +#: view:base.module.configuration:0 +msgid "" +"All pending configuration wizards have been executed. You may restart " +"individual wizards via the list of configuration wizards." +msgstr "" + +#. module: base +#: wizard_button:server.action.create,step_1,create:0 +msgid "Create" +msgstr "" + +#. module: base +#: view:ir.sequence:0 +msgid "Current Year with Century: %(year)s" +msgstr "" + +#. module: base +#: field:ir.exports,export_fields:0 +msgid "Export ID" +msgstr "" + +#. module: base +#: model:res.country,name:base.fr +msgid "France" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_log +msgid "res.log" +msgstr "" + +#. module: base +#: help:ir.translation,module:0 +#: help:ir.translation,xml_id:0 +msgid "Maps to the ir_model_data for which this translation is provided." +msgstr "" + +#. module: base +#: view:workflow.activity:0 +#: field:workflow.activity,flow_stop:0 +msgid "Flow Stop" +msgstr "" + +#. module: base +#: selection:ir.cron,interval_type:0 +msgid "Weeks" +msgstr "" + +#. module: base +#: model:res.country,name:base.af +msgid "Afghanistan, Islamic State of" +msgstr "" + +#. module: base +#: code:addons/base/module/wizard/base_module_import.py:67 +#, python-format +msgid "Error !" +msgstr "" + +#. module: base +#: model:res.partner.bank.type.field,name:base.bank_normal_field_contry +msgid "country_id" +msgstr "" + +#. module: base +#: field:ir.cron,interval_type:0 +msgid "Interval Unit" +msgstr "" + +#. module: base +#: field:publisher_warranty.contract,kind:0 +#: field:workflow.activity,kind:0 +msgid "Kind" +msgstr "" + +#. module: base +#: code:addons/orm.py:3775 +#, python-format +msgid "This method does not exist anymore" +msgstr "" + +#. module: base +#: field:res.bank,fax:0 +#: field:res.partner.address,fax:0 +msgid "Fax" +msgstr "" + +#. module: base +#: field:res.lang,thousands_sep:0 +msgid "Thousands Separator" +msgstr "" + +#. module: base +#: field:res.request,create_date:0 +msgid "Created Date" +msgstr "" + +#. module: base +#: help:ir.actions.server,loop_action:0 +msgid "" +"Select the action that will be executed. Loop action will not be avaliable " +"inside loop." +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Chinese (TW) / 正體字" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_request +msgid "res.request" +msgstr "" + +#. module: base +#: view:ir.model:0 +msgid "In Memory" +msgstr "" + +#. module: base +#: view:ir.actions.todo:0 +msgid "Todo" +msgstr "" + +#. module: base +#: field:ir.attachment,datas:0 +msgid "File Content" +msgstr "" + +#. module: base +#: model:res.country,name:base.pa +msgid "Panama" +msgstr "" + +#. module: base +#: model:res.partner.title,name:base.res_partner_title_ltd +msgid "Ltd" +msgstr "" + +#. module: base +#: help:workflow.transition,group_id:0 +msgid "" +"The group that a user must have to be authorized to validate this transition." +msgstr "" + +#. module: base +#: constraint:res.config.users:0 +#: constraint:res.users:0 +msgid "The chosen company is not in the allowed companies for this user" +msgstr "" + +#. module: base +#: model:res.country,name:base.gi +msgid "Gibraltar" +msgstr "" + +#. module: base +#: field:ir.actions.report.xml,report_name:0 +msgid "Service Name" +msgstr "" + +#. module: base +#: model:res.country,name:base.pn +msgid "Pitcairn Island" +msgstr "" + +#. module: base +#: view:base.module.upgrade:0 +msgid "" +"We suggest to reload the menu tab to see the new menus (Ctrl+T then Ctrl+R)." +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_rule +#: model:ir.ui.menu,name:base.menu_action_rule +msgid "Record Rules" +msgstr "" + +#. module: base +#: field:res.config.users,name:0 +#: field:res.users,name:0 +msgid "User Name" +msgstr "" + +#. module: base +#: view:ir.sequence:0 +msgid "Day of the year: %(doy)s" +msgstr "" + +#. module: base +#: view:ir.model:0 +#: view:ir.model.fields:0 +#: view:workflow.activity:0 +msgid "Properties" +msgstr "" + +#. module: base +#: help:ir.sequence,padding:0 +msgid "" +"OpenERP will automatically adds some '0' on the left of the 'Next Number' to " +"get the required padding size." +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "%A - Full weekday name." +msgstr "" + +#. module: base +#: selection:ir.cron,interval_type:0 +msgid "Months" +msgstr "" + +#. module: base +#: field:ir.actions.act_window,search_view:0 +msgid "Search View" +msgstr "" + +#. module: base +#: sql_constraint:res.lang:0 +msgid "The code of the language must be unique !" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_attachment +#: view:ir.actions.report.xml:0 +#: view:ir.attachment:0 +#: model:ir.ui.menu,name:base.menu_action_attachment +msgid "Attachments" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_base_partner +#: model:ir.ui.menu,name:base.menu_sale_config_sales +#: model:ir.ui.menu,name:base.menu_sales +msgid "Sales" +msgstr "" + +#. module: base +#: field:ir.actions.server,child_ids:0 +msgid "Other Actions" +msgstr "" + +#. module: base +#: selection:ir.actions.todo,state:0 +#: view:res.config.users:0 +msgid "Done" +msgstr "" + +#. module: base +#: model:res.partner.title,name:base.res_partner_title_miss +msgid "Miss" +msgstr "" + +#. module: base +#: view:ir.model.access:0 +#: field:ir.model.access,perm_write:0 +#: view:ir.rule:0 +msgid "Write Access" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "%m - Month number [01,12]." +msgstr "" + +#. module: base +#: field:res.bank,city:0 +#: field:res.partner,city:0 +#: field:res.partner.address,city:0 +#: field:res.partner.bank,city:0 +msgid "City" +msgstr "" + +#. module: base +#: model:res.country,name:base.qa +msgid "Qatar" +msgstr "" + +#. module: base +#: model:res.country,name:base.it +msgid "Italy" +msgstr "" + +#. module: base +#: view:ir.actions.todo:0 +#: selection:ir.actions.todo,state:0 +msgid "To Do" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Estonian / Eesti keel" +msgstr "" + +#. module: base +#: field:res.config.users,email:0 +#: field:res.partner,email:0 +#: field:res.users,email:0 +msgid "E-mail" +msgstr "" + +#. module: base +#: selection:ir.module.module,license:0 +msgid "GPL-3 or later version" +msgstr "" + +#. module: base +#: field:workflow.activity,action:0 +msgid "Python Action" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "English (US)" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_model_data +#: view:ir.model.data:0 +#: model:ir.ui.menu,name:base.ir_model_data_menu +msgid "Object Identifiers" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,help:base.action_partner_title_partner +msgid "" +"Manage the partner titles you want to have available in your system. The " +"partner titles is the legal status of the company: Private Limited, SA, etc." +msgstr "" + +#. module: base +#: view:base.language.export:0 +msgid "To browse official translations, you can start with these links:" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_model.py:484 +#, python-format +msgid "" +"You can not read this document (%s) ! Be sure your user belongs to one of " +"these groups: %s." +msgstr "" + +#. module: base +#: view:res.bank:0 +#: field:res.config.users,address_id:0 +#: view:res.partner.address:0 +#: view:res.users:0 +#: field:res.users,address_id:0 +msgid "Address" +msgstr "" + +#. module: base +#: field:ir.module.module,latest_version:0 +msgid "Installed version" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Mongolian / монгол" +msgstr "" + +#. module: base +#: model:res.country,name:base.mr +msgid "Mauritania" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_translation +msgid "ir.translation" +msgstr "" + +#. module: base +#: view:base.module.update:0 +msgid "Module update result" +msgstr "" + +#. module: base +#: view:workflow.activity:0 +#: field:workflow.workitem,act_id:0 +msgid "Activity" +msgstr "" + +#. module: base +#: view:res.partner:0 +#: view:res.partner.address:0 +msgid "Postal Address" +msgstr "" + +#. module: base +#: field:res.company,parent_id:0 +msgid "Parent Company" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Spanish (CR) / Español (CR)" +msgstr "" + +#. module: base +#: field:res.currency.rate,rate:0 +msgid "Rate" +msgstr "" + +#. module: base +#: model:res.country,name:base.cg +msgid "Congo" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "Examples" +msgstr "" + +#. module: base +#: field:ir.default,value:0 +msgid "Default Value" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_tools +msgid "Tools" +msgstr "" + +#. module: base +#: model:res.country,name:base.kn +msgid "Saint Kitts & Nevis Anguilla" +msgstr "" + +#. module: base +#: code:addons/base/res/res_currency.py:100 +#, python-format +msgid "" +"No rate found \n" +"for the currency: %s \n" +"at the date: %s" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,help:base.action_ui_view_custom +msgid "" +"Customized views are used when users reorganize the content of their " +"dashboard views (via web client)" +msgstr "" + +#. module: base +#: field:ir.model,name:0 +#: field:ir.model.fields,model:0 +#: field:ir.values,model:0 +msgid "Object Name" +msgstr "" + +#. module: base +#: help:ir.actions.server,srcmodel_id:0 +msgid "" +"Object in which you want to create / write the object. If it is empty then " +"refer to the Object field." +msgstr "" + +#. module: base +#: view:ir.module.module:0 +#: selection:ir.module.module,state:0 +#: selection:ir.module.module.dependency,state:0 +msgid "Not Installed" +msgstr "" + +#. module: base +#: view:workflow.activity:0 +#: field:workflow.activity,out_transitions:0 +msgid "Outgoing Transitions" +msgstr "" + +#. module: base +#: field:ir.ui.menu,icon:0 +msgid "Icon" +msgstr "" + +#. module: base +#: help:ir.model.fields,model_id:0 +msgid "The model this field belongs to" +msgstr "" + +#. module: base +#: model:res.country,name:base.mq +msgid "Martinique (French)" +msgstr "" + +#. module: base +#: view:ir.sequence.type:0 +msgid "Sequences Type" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.res_request-act +#: model:ir.ui.menu,name:base.menu_res_request_act +#: model:ir.ui.menu,name:base.menu_resquest_ref +#: view:res.request:0 +msgid "Requests" +msgstr "" + +#. module: base +#: model:res.country,name:base.ye +msgid "Yemen" +msgstr "" + +#. module: base +#: selection:workflow.activity,split_mode:0 +msgid "Or" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.res_log_act_window +#: model:ir.ui.menu,name:base.menu_res_log_act_window +msgid "Client Logs" +msgstr "" + +#. module: base +#: model:res.country,name:base.al +msgid "Albania" +msgstr "" + +#. module: base +#: model:res.country,name:base.ws +msgid "Samoa" +msgstr "" + +#. module: base +#: code:addons/base/res/res_lang.py:161 +#, python-format +msgid "" +"You cannot delete the language which is Active !\n" +"Please de-activate the language first." +msgstr "" + +#. module: base +#: view:base.language.install:0 +#: view:base.module.import:0 +msgid "" +"Please be patient, this operation may take a few minutes (depending on the " +"number of modules currently installed)..." +msgstr "" + +#. module: base +#: field:ir.ui.menu,child_id:0 +msgid "Child IDs" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_actions.py:713 +#: code:addons/base/ir/ir_actions.py:716 +#, python-format +msgid "Problem in configuration `Record Id` in Server Action!" +msgstr "" + +#. module: base +#: code:addons/orm.py:2306 +#: code:addons/orm.py:2316 +#, python-format +msgid "ValidateError" +msgstr "" + +#. module: base +#: view:base.module.import:0 +#: view:base.module.update:0 +msgid "Open Modules" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,help:base.action_res_bank_form +msgid "Manage bank records you want to be used in the system." +msgstr "" + +#. module: base +#: view:base.module.import:0 +msgid "Import module" +msgstr "" + +#. module: base +#: field:ir.actions.server,loop_action:0 +msgid "Loop Action" +msgstr "" + +#. module: base +#: help:ir.actions.report.xml,report_file:0 +msgid "" +"The path to the main report file (depending on Report Type) or NULL if the " +"content is in another field" +msgstr "" + +#. module: base +#: model:res.country,name:base.la +msgid "Laos" +msgstr "" + +#. module: base +#: selection:ir.actions.server,state:0 +#: field:res.config.users,user_email:0 +#: field:res.users,user_email:0 +msgid "Email" +msgstr "" + +#. module: base +#: field:res.config.users,action_id:0 +#: field:res.users,action_id:0 +msgid "Home Action" +msgstr "" + +#. module: base +#: code:addons/custom.py:558 +#, python-format +msgid "" +"The sum of the data (2nd field) is null.\n" +"We can't draw a pie chart !" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_lunch_reporting +#: model:ir.ui.menu,name:base.menu_project_report +#: model:ir.ui.menu,name:base.menu_report_association +#: model:ir.ui.menu,name:base.menu_report_marketing +#: model:ir.ui.menu,name:base.menu_reporting +#: model:ir.ui.menu,name:base.next_id_64 +#: model:ir.ui.menu,name:base.next_id_73 +#: model:ir.ui.menu,name:base.reporting_menu +msgid "Reporting" +msgstr "" + +#. module: base +#: model:res.country,name:base.tg +msgid "Togo" +msgstr "" + +#. module: base +#: selection:ir.module.module,license:0 +msgid "Other Proprietary" +msgstr "" + +#. module: base +#: selection:workflow.activity,kind:0 +msgid "Stop All" +msgstr "" + +#. module: base +#: code:addons/orm.py:412 +#, python-format +msgid "The read_group method is not implemented on this object !" +msgstr "" + +#. module: base +#: view:ir.model.data:0 +msgid "Updatable" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "3. %x ,%X ==> 12/05/08, 18:25:20" +msgstr "" + +#. module: base +#: selection:ir.model.fields,on_delete:0 +msgid "Cascade" +msgstr "" + +#. module: base +#: field:workflow.transition,group_id:0 +msgid "Group Required" +msgstr "" + +#. module: base +#: view:ir.actions.configuration.wizard:0 +msgid "Next Configuration Step" +msgstr "" + +#. module: base +#: field:res.groups,comment:0 +msgid "Comment" +msgstr "" + +#. module: base +#: model:res.country,name:base.ro +msgid "Romania" +msgstr "" + +#. module: base +#: help:ir.cron,doall:0 +msgid "" +"Enable this if you want to execute missed occurences as soon as the server " +"restarts." +msgstr "" + +#. module: base +#: view:base.module.upgrade:0 +msgid "Start update" +msgstr "" + +#. module: base +#: code:addons/base/publisher_warranty/publisher_warranty.py:144 +#, python-format +msgid "Contract validation error" +msgstr "" + +#. module: base +#: field:res.country.state,name:0 +msgid "State Name" +msgstr "" + +#. module: base +#: field:workflow.activity,join_mode:0 +msgid "Join Mode" +msgstr "" + +#. module: base +#: field:res.config.users,context_tz:0 +#: field:res.users,context_tz:0 +msgid "Timezone" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_actions_report_xml +#: selection:ir.ui.menu,action:0 +msgid "ir.actions.report.xml" +msgstr "" + +#. module: base +#: model:res.partner.title,shortcut:base.res_partner_title_miss +msgid "Mss" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_ui_view +msgid "ir.ui.view" +msgstr "" + +#. module: base +#: constraint:res.partner:0 +msgid "Error ! You can not create recursive associated members." +msgstr "" + +#. module: base +#: help:res.lang,code:0 +msgid "This field is used to set/get locales for user" +msgstr "" + +#. module: base +#: model:res.partner.category,name:base.res_partner_category_2 +msgid "OpenERP Partners" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_hr_manager +msgid "HR Manager Dashboard" +msgstr "" + +#. module: base +#: code:addons/base/module/module.py:253 +#, python-format +msgid "" +"Unable to install module \"%s\" because an external dependency is not met: %s" +msgstr "" + +#. module: base +#: view:ir.module.module:0 +msgid "Search modules" +msgstr "" + +#. module: base +#: model:res.country,name:base.by +msgid "Belarus" +msgstr "" + +#. module: base +#: field:ir.actions.act_window,name:0 +#: field:ir.actions.act_window_close,name:0 +#: field:ir.actions.actions,name:0 +#: field:ir.actions.server,name:0 +#: field:ir.actions.url,name:0 +#: field:ir.filters,name:0 +msgid "Action Name" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,help:base.action_res_users +msgid "" +"Create and manage users that will connect to the system. Users can be " +"deactivated should there be a period of time during which they will/should " +"not connect to the system. You can assign them groups in order to give them " +"specific access to the applications they need to use in the system." +msgstr "" + +#. module: base +#: selection:res.request,priority:0 +msgid "Normal" +msgstr "" + +#. module: base +#: field:res.bank,street2:0 +#: field:res.partner.address,street2:0 +msgid "Street2" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_view_base_module_update +msgid "Module Update" +msgstr "" + +#. module: base +#: code:addons/base/module/wizard/base_module_upgrade.py:95 +#, python-format +msgid "Following modules are not installed or unknown: %s" +msgstr "" + +#. module: base +#: view:ir.cron:0 +#: field:ir.cron,user_id:0 +#: view:ir.filters:0 +#: field:ir.filters,user_id:0 +#: field:ir.ui.view.custom,user_id:0 +#: field:ir.values,user_id:0 +#: field:res.log,user_id:0 +#: field:res.partner.event,user_id:0 +#: view:res.users:0 +#: field:res.widget.user,user_id:0 +msgid "User" +msgstr "" + +#. module: base +#: model:res.country,name:base.pr +msgid "Puerto Rico" +msgstr "" + +#. module: base +#: view:ir.actions.act_window:0 +msgid "Open Window" +msgstr "" + +#. module: base +#: field:ir.actions.act_window,auto_search:0 +msgid "Auto Search" +msgstr "" + +#. module: base +#: field:ir.actions.act_window,filter:0 +msgid "Filter" +msgstr "" + +#. module: base +#: model:res.partner.title,shortcut:base.res_partner_title_madam +msgid "Ms." +msgstr "" + +#. module: base +#: model:res.country,name:base.ch +msgid "Switzerland" +msgstr "" + +#. module: base +#: model:res.country,name:base.gd +msgid "Grenada" +msgstr "" + +#. module: base +#: model:res.country,name:base.wf +msgid "Wallis and Futuna Islands" +msgstr "" + +#. module: base +#: selection:server.action.create,init,type:0 +msgid "Open Report" +msgstr "" + +#. module: base +#: field:res.currency,rounding:0 +msgid "Rounding factor" +msgstr "" + +#. module: base +#: view:base.language.install:0 +msgid "Load" +msgstr "" + +#. module: base +#: help:res.config.users,name:0 +#: help:res.users,name:0 +msgid "The new user's real name, used for searching and most listings" +msgstr "" + +#. module: base +#: code:addons/osv.py:154 +#: code:addons/osv.py:156 +#, python-format +msgid "Integrity Error" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_wizard_screen +msgid "ir.wizard.screen" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_model.py:223 +#, python-format +msgid "Size of the field can never be less than 1 !" +msgstr "" + +#. module: base +#: model:res.country,name:base.so +msgid "Somalia" +msgstr "" + +#. module: base +#: selection:publisher_warranty.contract,state:0 +msgid "Terminated" +msgstr "" + +#. module: base +#: model:res.partner.category,name:base.res_partner_category_13 +msgid "Important customers" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "Update Terms" +msgstr "" + +#. module: base +#: field:partner.sms.send,mobile_to:0 +#: field:res.request,act_to:0 +#: field:res.request.history,act_to:0 +msgid "To" +msgstr "" + +#. module: base +#: view:ir.cron:0 +#: field:ir.cron,args:0 +msgid "Arguments" +msgstr "" + +#. module: base +#: code:addons/orm.py:716 +#, python-format +msgid "Database ID doesn't exist: %s : %s" +msgstr "" + +#. module: base +#: selection:ir.module.module,license:0 +msgid "GPL Version 2" +msgstr "" + +#. module: base +#: selection:ir.module.module,license:0 +msgid "GPL Version 3" +msgstr "" + +#. module: base +#: code:addons/orm.py:836 +#, python-format +msgid "key '%s' not found in selection field '%s'" +msgstr "" + +#. module: base +#: view:partner.wizard.ean.check:0 +msgid "Correct EAN13" +msgstr "" + +#. module: base +#: code:addons/orm.py:2317 +#, python-format +msgid "The value \"%s\" for the field \"%s\" is not in the selection" +msgstr "" + +#. module: base +#: field:res.partner,customer:0 +#: view:res.partner.address:0 +#: field:res.partner.address,is_customer_add:0 +#: model:res.partner.category,name:base.res_partner_category_0 +msgid "Customer" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Spanish (NI) / Español (NI)" +msgstr "" + +#. module: base +#: field:ir.module.module,shortdesc:0 +msgid "Short Description" +msgstr "" + +#. module: base +#: field:ir.actions.act_window,context:0 +#: field:ir.filters,context:0 +msgid "Context Value" +msgstr "" + +#. module: base +#: view:ir.sequence:0 +msgid "Hour 00->24: %(h24)s" +msgstr "" + +#. module: base +#: field:ir.cron,nextcall:0 +msgid "Next Execution Date" +msgstr "" + +#. module: base +#: help:multi_company.default,field_id:0 +msgid "Select field property" +msgstr "" + +#. module: base +#: field:res.request.history,date_sent:0 +msgid "Date sent" +msgstr "" + +#. module: base +#: view:ir.sequence:0 +msgid "Month: %(month)s" +msgstr "" + +#. module: base +#: field:ir.actions.act_window.view,sequence:0 +#: field:ir.actions.server,sequence:0 +#: field:ir.actions.todo,sequence:0 +#: view:ir.cron:0 +#: view:ir.sequence:0 +#: field:ir.ui.menu,sequence:0 +#: view:ir.ui.view:0 +#: field:ir.ui.view,priority:0 +#: field:ir.ui.view_sc,sequence:0 +#: field:multi_company.default,sequence:0 +#: field:res.partner.bank,sequence:0 +#: field:res.widget.user,sequence:0 +#: field:wizard.ir.model.menu.create.line,sequence:0 +msgid "Sequence" +msgstr "" + +#. module: base +#: model:res.country,name:base.tn +msgid "Tunisia" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_mrp_root +msgid "Manufacturing" +msgstr "" + +#. module: base +#: model:res.country,name:base.km +msgid "Comoros" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_server_action +#: view:ir.actions.server:0 +#: model:ir.ui.menu,name:base.menu_server_action +msgid "Server Actions" +msgstr "" + +#. module: base +#: view:ir.module.module:0 +msgid "Cancel Install" +msgstr "" + +#. module: base +#: field:ir.model.fields,selection:0 +msgid "Selection Options" +msgstr "" + +#. module: base +#: field:res.partner.category,parent_right:0 +msgid "Right parent" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "Legends for Date and Time Formats" +msgstr "" + +#. module: base +#: selection:ir.actions.server,state:0 +msgid "Copy Object" +msgstr "" + +#. module: base +#: code:addons/base/res/res_user.py:581 +#, python-format +msgid "" +"Group(s) cannot be deleted, because some user(s) still belong to them: %s !" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_country_state +#: model:ir.ui.menu,name:base.menu_country_state_partner +msgid "Fed. States" +msgstr "" + +#. module: base +#: view:ir.model:0 +#: view:res.groups:0 +msgid "Access Rules" +msgstr "" + +#. module: base +#: field:ir.default,ref_table:0 +msgid "Table Ref." +msgstr "" + +#. module: base +#: field:ir.actions.act_window,res_model:0 +#: field:ir.actions.report.xml,model:0 +#: field:ir.actions.server,model_id:0 +#: field:ir.actions.wizard,model:0 +#: field:ir.cron,model:0 +#: field:ir.default,field_tbl:0 +#: field:ir.filters,model_id:0 +#: field:ir.model,model:0 +#: view:ir.model.access:0 +#: field:ir.model.access,model_id:0 +#: view:ir.model.data:0 +#: field:ir.model.data,model:0 +#: view:ir.model.fields:0 +#: view:ir.rule:0 +#: field:ir.rule,model_id:0 +#: selection:ir.translation,type:0 +#: view:ir.ui.view:0 +#: field:ir.ui.view,model:0 +#: view:ir.values:0 +#: field:ir.values,model_id:0 +#: field:multi_company.default,object_id:0 +#: field:res.log,res_model:0 +#: field:res.request.link,object:0 +#: field:workflow.triggers,model:0 +msgid "Object" +msgstr "" + +#. module: base +#: code:addons/osv.py:151 +#, python-format +msgid "" +"\n" +"\n" +"[object with reference: %s - %s]" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_default +msgid "ir.default" +msgstr "" + +#. module: base +#: view:ir.sequence:0 +msgid "Minute: %(min)s" +msgstr "" + +#. module: base +#: view:base.update.translations:0 +#: model:ir.actions.act_window,name:base.action_wizard_update_translations +#: model:ir.ui.menu,name:base.menu_wizard_update_translations +msgid "Synchronize Translations" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.next_id_10 +msgid "Scheduler" +msgstr "" + +#. module: base +#: help:ir.cron,numbercall:0 +msgid "" +"Number of time the function is called,\n" +"a negative number indicates no limit" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_model.py:331 +#, python-format +msgid "" +"Changing the type of a column is not yet supported. Please drop it and " +"create it again!" +msgstr "" + +#. module: base +#: field:ir.ui.view_sc,user_id:0 +msgid "User Ref." +msgstr "" + +#. module: base +#: code:addons/base/res/res_user.py:580 +#, python-format +msgid "Warning !" +msgstr "" + +#. module: base +#: model:res.widget,title:base.google_maps_widget +msgid "Google Maps" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_base_config +#: model:ir.ui.menu,name:base.menu_config +#: model:ir.ui.menu,name:base.menu_event_config +#: model:ir.ui.menu,name:base.menu_lunch_survey_root +#: model:ir.ui.menu,name:base.menu_marketing_config_association +#: model:ir.ui.menu,name:base.menu_marketing_config_root +#: view:res.company:0 +msgid "Configuration" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_publisher_warranty_contract_wizard +msgid "publisher_warranty.contract.wizard" +msgstr "" + +#. module: base +#: field:ir.actions.server,expression:0 +msgid "Loop Expression" +msgstr "" + +#. module: base +#: field:publisher_warranty.contract,date_start:0 +msgid "Starting Date" +msgstr "" + +#. module: base +#: help:res.partner,website:0 +msgid "Website of Partner" +msgstr "" + +#. module: base +#: model:res.partner.category,name:base.res_partner_category_5 +msgid "Gold Partner" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_partner +#: field:res.company,partner_id:0 +#: view:res.partner.address:0 +#: field:res.partner.bank,partner_id:0 +#: field:res.partner.event,partner_id:0 +#: selection:res.partner.title,domain:0 +#: model:res.request.link,name:base.req_link_partner +msgid "Partner" +msgstr "" + +#. module: base +#: model:res.country,name:base.tr +msgid "Turkey" +msgstr "" + +#. module: base +#: model:res.country,name:base.fk +msgid "Falkland Islands" +msgstr "" + +#. module: base +#: model:res.country,name:base.lb +msgid "Lebanon" +msgstr "" + +#. module: base +#: view:ir.actions.report.xml:0 +#: field:ir.actions.report.xml,report_type:0 +msgid "Report Type" +msgstr "" + +#. module: base +#: field:ir.actions.todo,state:0 +#: view:ir.module.module:0 +#: field:ir.module.module,state:0 +#: field:ir.module.module.dependency,state:0 +#: field:publisher_warranty.contract,state:0 +#: field:res.bank,state:0 +#: view:res.country.state:0 +#: field:res.partner.bank,state_id:0 +#: view:res.request:0 +#: field:res.request,state:0 +#: field:workflow.instance,state:0 +#: field:workflow.workitem,state:0 +msgid "State" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Galician / Galego" +msgstr "" + +#. module: base +#: model:res.country,name:base.no +msgid "Norway" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "4. %b, %B ==> Dec, December" +msgstr "" + +#. module: base +#: view:base.language.install:0 +#: model:ir.ui.menu,name:base.menu_view_base_language_install +msgid "Load an Official Translation" +msgstr "" + +#. module: base +#: view:res.currency:0 +msgid "Miscelleanous" +msgstr "" + +#. module: base +#: model:res.partner.category,name:base.res_partner_category_10 +msgid "Open Source Service Company" +msgstr "" + +#. module: base +#: model:res.country,name:base.kg +msgid "Kyrgyz Republic (Kyrgyzstan)" +msgstr "" + +#. module: base +#: selection:res.request,state:0 +msgid "waiting" +msgstr "" + +#. module: base +#: field:ir.actions.report.xml,report_file:0 +msgid "Report file" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_workflow_triggers +msgid "workflow.triggers" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_model.py:62 +#, python-format +msgid "Invalid search criterions" +msgstr "" + +#. module: base +#: view:ir.attachment:0 +msgid "Created" +msgstr "" + +#. module: base +#: help:ir.actions.wizard,multi:0 +msgid "" +"If set to true, the wizard will not be displayed on the right toolbar of a " +"form view." +msgstr "" + +#. module: base +#: view:base.language.import:0 +msgid "- type,name,res_id,src,value" +msgstr "" + +#. module: base +#: model:res.country,name:base.hm +msgid "Heard and McDonald Islands" +msgstr "" + +#. module: base +#: field:ir.actions.act_window,view_id:0 +msgid "View Ref." +msgstr "" + +#. module: base +#: selection:ir.translation,type:0 +msgid "Selection" +msgstr "" + +#. module: base +#: field:res.company,rml_header1:0 +msgid "Report Header" +msgstr "" + +#. module: base +#: field:ir.actions.act_window,type:0 +#: field:ir.actions.act_window_close,type:0 +#: field:ir.actions.actions,type:0 +#: field:ir.actions.report.xml,type:0 +#: view:ir.actions.server:0 +#: field:ir.actions.server,state:0 +#: field:ir.actions.server,type:0 +#: field:ir.actions.url,type:0 +#: field:ir.actions.wizard,type:0 +msgid "Action Type" +msgstr "" + +#. module: base +#: code:addons/base/module/module.py:268 +#, python-format +msgid "" +"You try to install module '%s' that depends on module '%s'.\n" +"But the latter module is not available in your system." +msgstr "" + +#. module: base +#: view:base.language.import:0 +#: model:ir.actions.act_window,name:base.action_view_base_import_language +#: model:ir.ui.menu,name:base.menu_view_base_import_language +msgid "Import Translation" +msgstr "" + +#. module: base +#: field:res.partner.bank.type,field_ids:0 +msgid "Type fields" +msgstr "" + +#. module: base +#: view:ir.module.module:0 +#: field:ir.module.module,category_id:0 +msgid "Category" +msgstr "" + +#. module: base +#: view:ir.attachment:0 +#: selection:ir.attachment,type:0 +#: selection:ir.property,type:0 +msgid "Binary" +msgstr "" + +#. module: base +#: field:ir.actions.server,sms:0 +#: selection:ir.actions.server,state:0 +msgid "SMS" +msgstr "" + +#. module: base +#: model:res.country,name:base.cr +msgid "Costa Rica" +msgstr "" + +#. module: base +#: view:workflow.activity:0 +msgid "Conditions" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_partner_other_form +msgid "Other Partners" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_currency_form +#: model:ir.ui.menu,name:base.menu_action_currency_form +#: view:res.currency:0 +msgid "Currencies" +msgstr "" + +#. module: base +#: sql_constraint:res.groups:0 +msgid "The name of the group must be unique !" +msgstr "" + +#. module: base +#: view:ir.sequence:0 +msgid "Hour 00->12: %(h12)s" +msgstr "" + +#. module: base +#: help:res.partner.address,active:0 +msgid "Uncheck the active field to hide the contact." +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_widget_wizard +msgid "Add a widget for User" +msgstr "" + +#. module: base +#: model:res.country,name:base.dk +msgid "Denmark" +msgstr "" + +#. module: base +#: field:res.country,code:0 +msgid "Country Code" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_workflow_instance +msgid "workflow.instance" +msgstr "" + +#. module: base +#: code:addons/orm.py:278 +#, python-format +msgid "Unknown attribute %s in %s " +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "10. %S ==> 20" +msgstr "" + +#. module: base +#: code:addons/fields.py:106 +#, python-format +msgid "undefined get method !" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Norwegian Bokmål / Norsk bokmål" +msgstr "" + +#. module: base +#: help:res.config.users,new_password:0 +#: help:res.users,new_password:0 +msgid "" +"Only specify a value if you want to change the user password. This user will " +"have to logout and login again!" +msgstr "" + +#. module: base +#: model:res.partner.title,name:base.res_partner_title_madam +msgid "Madam" +msgstr "" + +#. module: base +#: model:res.country,name:base.ee +msgid "Estonia" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.dashboard +msgid "Dashboards" +msgstr "" + +#. module: base +#: help:ir.attachment,type:0 +msgid "Binary File or external URL" +msgstr "" + +#. module: base +#: field:res.config.users,new_password:0 +#: field:res.users,new_password:0 +msgid "Change password" +msgstr "" + +#. module: base +#: model:res.country,name:base.nl +msgid "Netherlands" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.next_id_4 +msgid "Low Level Objects" +msgstr "" + +#. module: base +#: view:res.company:0 +msgid "Your Logo - Use a size of about 450x150 pixels." +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_values +msgid "ir.values" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Occitan (FR, post 1500) / Occitan" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,help:base.open_module_tree +msgid "" +"You can install new modules in order to activate new features, menu, reports " +"or data in your OpenERP instance. To install some modules, click on the " +"button \"Schedule for Installation\" from the form view, then click on " +"\"Apply Scheduled Upgrades\" to migrate your system." +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_emails +#: model:ir.ui.menu,name:base.menu_mail_gateway +msgid "Emails" +msgstr "" + +#. module: base +#: model:res.country,name:base.cd +msgid "Congo, The Democratic Republic of the" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Malayalam / മലയാളം" +msgstr "" + +#. module: base +#: view:res.request:0 +#: field:res.request,body:0 +#: field:res.request.history,req_id:0 +msgid "Request" +msgstr "" + +#. module: base +#: model:res.country,name:base.jp +msgid "Japan" +msgstr "" + +#. module: base +#: field:ir.cron,numbercall:0 +msgid "Number of Calls" +msgstr "" + +#. module: base +#: view:base.module.upgrade:0 +#: field:base.module.upgrade,module_info:0 +msgid "Modules to update" +msgstr "" + +#. module: base +#: help:ir.actions.server,sequence:0 +msgid "" +"Important when you deal with multiple actions, the execution order will be " +"decided based on this, low number is higher priority." +msgstr "" + +#. module: base +#: field:ir.actions.report.xml,header:0 +msgid "Add RML header" +msgstr "" + +#. module: base +#: model:res.country,name:base.gr +msgid "Greece" +msgstr "" + +#. module: base +#: field:res.request,trigger_date:0 +msgid "Trigger Date" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Croatian / hrvatski jezik" +msgstr "" + +#. module: base +#: field:base.language.install,overwrite:0 +msgid "Overwrite Existing Terms" +msgstr "" + +#. module: base +#: help:ir.actions.server,code:0 +msgid "Python code to be executed" +msgstr "" + +#. module: base +#: sql_constraint:res.country:0 +msgid "The code of the country must be unique !" +msgstr "" + +#. module: base +#: selection:ir.module.module.dependency,state:0 +msgid "Uninstallable" +msgstr "" + +#. module: base +#: view:res.partner.category:0 +msgid "Partner Category" +msgstr "" + +#. module: base +#: view:ir.actions.server:0 +#: selection:ir.actions.server,state:0 +msgid "Trigger" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_base_module_update +msgid "Update Module" +msgstr "" + +#. module: base +#: view:ir.model.fields:0 +#: field:ir.model.fields,translate:0 +msgid "Translate" +msgstr "" + +#. module: base +#: field:res.request.history,body:0 +msgid "Body" +msgstr "" + +#. module: base +#: view:partner.wizard.spam:0 +msgid "Send Email" +msgstr "" + +#. module: base +#: field:res.config.users,menu_id:0 +#: field:res.users,menu_id:0 +msgid "Menu Action" +msgstr "" + +#. module: base +#: help:ir.model.fields,selection:0 +msgid "" +"List of options for a selection field, specified as a Python expression " +"defining a list of (key, label) pairs. For example: " +"[('blue','Blue'),('yellow','Yellow')]" +msgstr "" + +#. module: base +#: selection:base.language.export,state:0 +msgid "choose" +msgstr "" + +#. module: base +#: help:ir.model,osv_memory:0 +msgid "" +"Indicates whether this object model lives in memory only, i.e. is not " +"persisted (osv.osv_memory)" +msgstr "" + +#. module: base +#: field:res.partner,child_ids:0 +#: field:res.request,ref_partner_id:0 +msgid "Partner Ref." +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_partner_supplier_form +#: model:ir.ui.menu,name:base.menu_procurement_management_supplier_name +#: view:res.partner:0 +msgid "Suppliers" +msgstr "" + +#. module: base +#: view:publisher_warranty.contract.wizard:0 +msgid "Register" +msgstr "" + +#. module: base +#: field:res.request,ref_doc2:0 +msgid "Document Ref 2" +msgstr "" + +#. module: base +#: field:res.request,ref_doc1:0 +msgid "Document Ref 1" +msgstr "" + +#. module: base +#: model:res.country,name:base.ga +msgid "Gabon" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_model_data +msgid "ir.model.data" +msgstr "" + +#. module: base +#: view:ir.model:0 +#: view:ir.rule:0 +#: view:res.groups:0 +msgid "Access Rights" +msgstr "" + +#. module: base +#: model:res.country,name:base.gl +msgid "Greenland" +msgstr "" + +#. module: base +#: field:res.partner.bank,acc_number:0 +msgid "Account Number" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "1. %c ==> Fri Dec 5 18:25:20 2008" +msgstr "" + +#. module: base +#: model:res.country,name:base.nc +msgid "New Caledonia (French)" +msgstr "" + +#. module: base +#: model:res.country,name:base.cy +msgid "Cyprus" +msgstr "" + +#. module: base +#: view:base.module.import:0 +msgid "" +"This wizard helps you add a new language to you OpenERP system. After " +"loading a new language it becomes available as default interface language " +"for users and partners." +msgstr "" + +#. module: base +#: field:ir.actions.server,subject:0 +#: field:partner.wizard.spam,subject:0 +#: field:res.request,name:0 +msgid "Subject" +msgstr "" + +#. module: base +#: field:res.request,act_from:0 +#: field:res.request.history,act_from:0 +msgid "From" +msgstr "" + +#. module: base +#: view:res.users:0 +msgid "Preferences" +msgstr "" + +#. module: base +#: model:res.partner.category,name:base.res_partner_category_consumers0 +msgid "Consumers" +msgstr "" + +#. module: base +#: view:res.config:0 +#: wizard_button:server.action.create,init,step_1:0 +msgid "Next" +msgstr "" + +#. module: base +#: help:ir.cron,function:0 +msgid "" +"Name of the method to be called on the object when this scheduler is " +"executed." +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_model.py:219 +#, python-format +msgid "" +"The Selection Options expression is must be in the [('key','Label'), ...] " +"format!" +msgstr "" + +#. module: base +#: view:ir.actions.report.xml:0 +msgid "Miscellaneous" +msgstr "" + +#. module: base +#: model:res.country,name:base.cn +msgid "China" +msgstr "" + +#. module: base +#: code:addons/base/res/res_user.py:516 +#, python-format +msgid "" +"--\n" +"%(name)s %(email)s\n" +msgstr "" + +#. module: base +#: model:res.country,name:base.eh +msgid "Western Sahara" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_workflow +msgid "workflow" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,help:base.action_res_company_form +msgid "" +"Create and manage the companies that will be managed by OpenERP from here. " +"Shops or subsidiaries can be created and maintained from here." +msgstr "" + +#. module: base +#: model:res.country,name:base.id +msgid "Indonesia" +msgstr "" + +#. module: base +#: view:base.update.translations:0 +msgid "" +"This wizard will detect new terms to translate in the application, so that " +"you can then add translations manually or perform a complete export (as a " +"template for a new language example)." +msgstr "" + +#. module: base +#: help:multi_company.default,expression:0 +msgid "" +"Expression, must be True to match\n" +"use context.get or user (browse)" +msgstr "" + +#. module: base +#: model:res.country,name:base.bg +msgid "Bulgaria" +msgstr "" + +#. module: base +#: view:publisher_warranty.contract.wizard:0 +msgid "Publisher warranty contract successfully registered!" +msgstr "" + +#. module: base +#: model:res.country,name:base.ao +msgid "Angola" +msgstr "" + +#. module: base +#: model:res.country,name:base.tf +msgid "French Southern Territories" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_currency +#: field:res.company,currency_id:0 +#: field:res.company,currency_ids:0 +#: view:res.currency:0 +#: field:res.currency,name:0 +#: field:res.currency.rate,currency_id:0 +msgid "Currency" +msgstr "" + +#. module: base +#: field:res.partner.canal,name:0 +msgid "Channel Name" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "5. %y, %Y ==> 08, 2008" +msgstr "" + +#. module: base +#: model:res.partner.title,shortcut:base.res_partner_title_ltd +msgid "ltd" +msgstr "" + +#. module: base +#: field:ir.values,res_id:0 +#: field:res.log,res_id:0 +msgid "Object ID" +msgstr "" + +#. module: base +#: view:res.company:0 +msgid "Landscape" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_administration +msgid "Administration" +msgstr "" + +#. module: base +#: view:base.module.update:0 +msgid "Click on Update below to start the process..." +msgstr "" + +#. module: base +#: model:res.country,name:base.ir +msgid "Iran" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.res_widget_user_act_window +#: model:ir.ui.menu,name:base.menu_res_widget_user_act_window +msgid "Widgets per User" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Slovak / Slovenský jazyk" +msgstr "" + +#. module: base +#: field:base.language.export,state:0 +#: field:ir.ui.menu,icon_pict:0 +#: field:publisher_warranty.contract.wizard,state:0 +msgid "unknown" +msgstr "" + +#. module: base +#: field:res.currency,symbol:0 +msgid "Symbol" +msgstr "" + +#. module: base +#: help:res.config.users,login:0 +#: help:res.users,login:0 +msgid "Used to log into the system" +msgstr "" + +#. module: base +#: view:base.update.translations:0 +msgid "Synchronize Translation" +msgstr "" + +#. module: base +#: field:ir.ui.view_sc,res_id:0 +msgid "Resource Ref." +msgstr "" + +#. module: base +#: model:res.country,name:base.ki +msgid "Kiribati" +msgstr "" + +#. module: base +#: model:res.country,name:base.iq +msgid "Iraq" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_association +msgid "Association" +msgstr "" + +#. module: base +#: model:res.country,name:base.cl +msgid "Chile" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_address_book +#: model:ir.ui.menu,name:base.menu_config_address_book +#: model:ir.ui.menu,name:base.menu_procurement_management_supplier +msgid "Address Book" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_sequence_type +msgid "ir.sequence.type" +msgstr "" + +#. module: base +#: selection:base.language.export,format:0 +msgid "CSV File" +msgstr "" + +#. module: base +#: field:res.company,account_no:0 +msgid "Account No." +msgstr "" + +#. module: base +#: code:addons/base/res/res_lang.py:157 +#, python-format +msgid "Base Language 'en_US' can not be deleted !" +msgstr "" + +#. module: base +#: selection:ir.model,state:0 +msgid "Base Object" +msgstr "" + +#. module: base +#: report:ir.module.reference.graph:0 +msgid "Dependencies :" +msgstr "" + +#. module: base +#: field:ir.model.fields,field_description:0 +msgid "Field Label" +msgstr "" + +#. module: base +#: model:res.country,name:base.dj +msgid "Djibouti" +msgstr "" + +#. module: base +#: field:ir.translation,value:0 +msgid "Translation Value" +msgstr "" + +#. module: base +#: model:res.country,name:base.ag +msgid "Antigua and Barbuda" +msgstr "" + +#. module: base +#: code:addons/orm.py:3166 +#, python-format +msgid "" +"Operation prohibited by access rules, or performed on an already deleted " +"document (Operation: %s, Document type: %s)." +msgstr "" + +#. module: base +#: model:res.country,name:base.zr +msgid "Zaire" +msgstr "" + +#. module: base +#: field:ir.model.data,res_id:0 +#: field:ir.translation,res_id:0 +#: field:workflow.instance,res_id:0 +#: field:workflow.triggers,res_id:0 +msgid "Resource ID" +msgstr "" + +#. module: base +#: view:ir.cron:0 +#: field:ir.model,info:0 +msgid "Information" +msgstr "" + +#. module: base +#: view:res.widget.user:0 +msgid "User Widgets" +msgstr "" + +#. module: base +#: view:base.module.update:0 +msgid "Update Module List" +msgstr "" + +#. module: base +#: selection:res.partner.address,type:0 +msgid "Other" +msgstr "" + +#. module: base +#: view:res.request:0 +msgid "Reply" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Turkish / Türkçe" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_workflow_activity_form +#: model:ir.ui.menu,name:base.menu_workflow_activity +#: view:workflow:0 +#: field:workflow,activities:0 +msgid "Activities" +msgstr "" + +#. module: base +#: field:ir.actions.act_window,auto_refresh:0 +msgid "Auto-Refresh" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_model.py:62 +#, python-format +msgid "The osv_memory field can only be compared with = and != operator." +msgstr "" + +#. module: base +#: selection:ir.ui.view,type:0 +msgid "Diagram" +msgstr "" + +#. module: base +#: help:multi_company.default,name:0 +msgid "Name it to easily find a record" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.grant_menu_access +#: model:ir.ui.menu,name:base.menu_grant_menu_access +msgid "Menu Items" +msgstr "" + +#. module: base +#: constraint:ir.rule:0 +msgid "Rules are not supported for osv_memory objects !" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_event_association +#: model:ir.ui.menu,name:base.menu_event_main +msgid "Events Organisation" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.ir_sequence_actions +#: model:ir.ui.menu,name:base.menu_custom_action +#: model:ir.ui.menu,name:base.menu_ir_sequence_actions +#: model:ir.ui.menu,name:base.next_id_6 +#: view:workflow.activity:0 +msgid "Actions" +msgstr "" + +#. module: base +#: selection:res.request,priority:0 +msgid "High" +msgstr "" + +#. module: base +#: field:ir.exports.line,export_id:0 +msgid "Export" +msgstr "" + +#. module: base +#: model:res.country,name:base.hr +msgid "Croatia" +msgstr "" + +#. module: base +#: help:res.bank,bic:0 +msgid "Bank Identifier Code" +msgstr "" + +#. module: base +#: model:res.country,name:base.tm +msgid "Turkmenistan" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_actions.py:597 +#: code:addons/base/ir/ir_actions.py:629 +#: code:addons/base/ir/ir_actions.py:713 +#: code:addons/base/ir/ir_actions.py:716 +#: code:addons/base/ir/ir_model.py:114 +#: code:addons/base/ir/ir_model.py:204 +#: code:addons/base/ir/ir_model.py:218 +#: code:addons/base/ir/ir_model.py:232 +#: code:addons/base/ir/ir_model.py:250 +#: code:addons/base/ir/ir_model.py:255 +#: code:addons/base/ir/ir_model.py:258 +#: code:addons/base/module/module.py:215 +#: code:addons/base/module/module.py:258 +#: code:addons/base/module/module.py:262 +#: code:addons/base/module/module.py:268 +#: code:addons/base/module/module.py:303 +#: code:addons/base/module/module.py:321 +#: code:addons/base/module/module.py:336 +#: code:addons/base/module/module.py:429 +#: code:addons/base/module/module.py:531 +#: code:addons/base/publisher_warranty/publisher_warranty.py:163 +#: code:addons/base/publisher_warranty/publisher_warranty.py:281 +#: code:addons/base/res/res_currency.py:100 +#: code:addons/base/res/res_user.py:57 +#: code:addons/base/res/res_user.py:66 +#: code:addons/custom.py:558 +#: code:addons/orm.py:3199 +#, python-format +msgid "Error" +msgstr "" + +#. module: base +#: model:res.country,name:base.pm +msgid "Saint Pierre and Miquelon" +msgstr "" + +#. module: base +#: help:ir.actions.report.xml,header:0 +msgid "Add or not the coporate RML header" +msgstr "" + +#. module: base +#: help:workflow.transition,act_to:0 +msgid "The destination activity." +msgstr "" + +#. module: base +#: view:base.module.update:0 +#: view:base.update.translations:0 +msgid "Update" +msgstr "" + +#. module: base +#: model:ir.actions.report.xml,name:base.ir_module_reference_print +msgid "Technical guide" +msgstr "" + +#. module: base +#: model:res.country,name:base.tz +msgid "Tanzania" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Danish / Dansk" +msgstr "" + +#. module: base +#: selection:ir.model.fields,select_level:0 +msgid "Advanced Search (deprecated)" +msgstr "" + +#. module: base +#: model:res.country,name:base.cx +msgid "Christmas Island" +msgstr "" + +#. module: base +#: view:ir.actions.server:0 +msgid "Other Actions Configuration" +msgstr "" + +#. module: base +#: view:res.config.installer:0 +msgid "Install Modules" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.res_partner_canal-act +#: model:ir.model,name:base.model_res_partner_canal +#: model:ir.ui.menu,name:base.menu_res_partner_canal-act +#: view:res.partner.canal:0 +msgid "Channels" +msgstr "" + +#. module: base +#: view:ir.ui.view:0 +msgid "Extra Info" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.act_values_form_action +#: model:ir.ui.menu,name:base.menu_values_form_action +msgid "Client Events" +msgstr "" + +#. module: base +#: view:ir.module.module:0 +msgid "Schedule for Installation" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_partner_wizard_ean_check +msgid "Ean Check" +msgstr "" + +#. module: base +#: sql_constraint:res.config.users:0 +#: sql_constraint:res.users:0 +msgid "You can not have two users with the same login !" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_multi_company_default +msgid "Default multi company" +msgstr "" + +#. module: base +#: view:res.request:0 +msgid "Send" +msgstr "" + +#. module: base +#: field:res.config.users,menu_tips:0 +#: field:res.users,menu_tips:0 +msgid "Menu Tips" +msgstr "" + +#. module: base +#: field:ir.translation,src:0 +msgid "Source" +msgstr "" + +#. module: base +#: help:res.partner.address,partner_id:0 +msgid "Keep empty for a private address, not related to partner." +msgstr "" + +#. module: base +#: model:res.country,name:base.vu +msgid "Vanuatu" +msgstr "" + +#. module: base +#: view:res.company:0 +msgid "Internal Header/Footer" +msgstr "" + +#. module: base +#: code:addons/base/module/wizard/base_export_language.py:59 +#, python-format +msgid "" +"Save this document to a .tgz file. This archive containt UTF-8 %s files and " +"may be uploaded to launchpad." +msgstr "" + +#. module: base +#: view:base.module.upgrade:0 +msgid "Start configuration" +msgstr "" + +#. module: base +#: view:base.language.export:0 +msgid "_Export" +msgstr "" + +#. module: base +#: field:base.language.install,state:0 +#: field:base.module.import,state:0 +#: field:base.module.update,state:0 +msgid "state" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Catalan / Català" +msgstr "" + +#. module: base +#: model:res.country,name:base.do +msgid "Dominican Republic" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Serbian (Cyrillic) / српски" +msgstr "" + +#. module: base +#: code:addons/orm.py:2161 +#, python-format +msgid "" +"Invalid group_by specification: \"%s\".\n" +"A group_by specification must be a list of valid fields." +msgstr "" + +#. module: base +#: model:res.country,name:base.sa +msgid "Saudi Arabia" +msgstr "" + +#. module: base +#: help:res.partner,supplier:0 +msgid "" +"Check this box if the partner is a supplier. If it's not checked, purchase " +"people will not see it when encoding a purchase order." +msgstr "" + +#. module: base +#: field:ir.model.fields,relation_field:0 +msgid "Relation Field" +msgstr "" + +#. module: base +#: view:res.partner.event:0 +msgid "Event Logs" +msgstr "" + +#. module: base +#: code:addons/base/module/wizard/base_module_configuration.py:37 +#, python-format +msgid "System Configuration done" +msgstr "" + +#. module: base +#: field:workflow.triggers,instance_id:0 +msgid "Destination Instance" +msgstr "" + +#. module: base +#: field:ir.actions.act_window,multi:0 +#: field:ir.actions.wizard,multi:0 +msgid "Action on Multiple Doc." +msgstr "" + +#. module: base +#: view:base.language.export:0 +msgid "https://translations.launchpad.net/openobject" +msgstr "" + +#. module: base +#: field:ir.actions.report.xml,report_xml:0 +msgid "XML path" +msgstr "" + +#. module: base +#: selection:ir.actions.todo,restart:0 +msgid "On Skip" +msgstr "" + +#. module: base +#: model:res.country,name:base.gn +msgid "Guinea" +msgstr "" + +#. module: base +#: model:res.country,name:base.lu +msgid "Luxembourg" +msgstr "" + +#. module: base +#: help:ir.values,key2:0 +msgid "" +"The kind of action or button in the client side that will trigger the action." +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_ui_menu.py:285 +#, python-format +msgid "Error ! You can not create recursive Menu." +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_publisher_warranty_contract_add_wizard +#: model:ir.ui.menu,name:base.menu_publisher_warranty_contract_add +#: view:publisher_warranty.contract.wizard:0 +msgid "Register a Contract" +msgstr "" + +#. module: base +#: view:ir.rule:0 +msgid "" +"3. If user belongs to several groups, the results from step 2 are combined " +"with logical OR operator" +msgstr "" + +#. module: base +#: code:addons/base/publisher_warranty/publisher_warranty.py:145 +#, python-format +msgid "Please check your publisher warranty contract name and validity." +msgstr "" + +#. module: base +#: model:res.country,name:base.sv +msgid "El Salvador" +msgstr "" + +#. module: base +#: field:res.bank,phone:0 +#: field:res.partner,phone:0 +#: field:res.partner.address,phone:0 +msgid "Phone" +msgstr "" + +#. module: base +#: field:ir.cron,active:0 +#: field:ir.sequence,active:0 +#: field:res.bank,active:0 +#: field:res.config.users,active:0 +#: field:res.currency,active:0 +#: field:res.lang,active:0 +#: field:res.partner,active:0 +#: field:res.partner.address,active:0 +#: field:res.partner.canal,active:0 +#: field:res.partner.category,active:0 +#: field:res.request,active:0 +#: field:res.users,active:0 +#: view:workflow.instance:0 +#: view:workflow.workitem:0 +msgid "Active" +msgstr "" + +#. module: base +#: model:res.country,name:base.th +msgid "Thailand" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_crm_config_lead +msgid "Leads & Opportunities" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Romanian / română" +msgstr "" + +#. module: base +#: view:res.log:0 +msgid "System Logs" +msgstr "" + +#. module: base +#: selection:workflow.activity,join_mode:0 +#: selection:workflow.activity,split_mode:0 +msgid "And" +msgstr "" + +#. module: base +#: field:ir.model.fields,relation:0 +msgid "Object Relation" +msgstr "" + +#. module: base +#: view:ir.rule:0 +#: view:res.partner:0 +msgid "General" +msgstr "" + +#. module: base +#: model:res.country,name:base.uz +msgid "Uzbekistan" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_actions_act_window +#: selection:ir.ui.menu,action:0 +msgid "ir.actions.act_window" +msgstr "" + +#. module: base +#: field:ir.rule,perm_create:0 +msgid "Apply For Create" +msgstr "" + +#. module: base +#: model:res.country,name:base.vi +msgid "Virgin Islands (USA)" +msgstr "" + +#. module: base +#: model:res.country,name:base.tw +msgid "Taiwan" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_currency_rate +msgid "Currency Rate" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,help:base.grant_menu_access +msgid "" +"Manage and customize the items available and displayed in your OpenERP " +"system menu. You can delete an item by clicking on the box at the beginning " +"of each line and then delete it through the button that appeared. Items can " +"be assigned to specific groups in order to make them accessible to some " +"users within the system." +msgstr "" + +#. module: base +#: field:ir.ui.view,field_parent:0 +msgid "Child Field" +msgstr "" + +#. module: base +#: field:ir.actions.act_window,usage:0 +#: field:ir.actions.act_window_close,usage:0 +#: field:ir.actions.actions,usage:0 +#: field:ir.actions.report.xml,usage:0 +#: field:ir.actions.server,usage:0 +#: field:ir.actions.wizard,usage:0 +msgid "Action Usage" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_workflow_workitem +msgid "workflow.workitem" +msgstr "" + +#. module: base +#: selection:ir.module.module,state:0 +msgid "Not Installable" +msgstr "" + +#. module: base +#: report:ir.module.reference.graph:0 +msgid "View :" +msgstr "" + +#. module: base +#: field:ir.model.fields,view_load:0 +msgid "View Auto-Load" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_model.py:232 +#, python-format +msgid "You cannot remove the field '%s' !" +msgstr "" + +#. module: base +#: field:ir.exports,resource:0 +#: view:ir.property:0 +#: field:ir.property,res_id:0 +msgid "Resource" +msgstr "" + +#. module: base +#: field:ir.ui.menu,web_icon:0 +msgid "Web Icon File" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Persian / فارس" +msgstr "" + +#. module: base +#: view:ir.actions.act_window:0 +msgid "View Ordering" +msgstr "" + +#. module: base +#: code:addons/base/module/wizard/base_module_upgrade.py:95 +#, python-format +msgid "Unmet dependency !" +msgstr "" + +#. module: base +#: view:base.language.import:0 +msgid "" +"Supported file formats: *.csv (Comma-separated values) or *.po (GetText " +"Portable Objects)" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_model.py:487 +#, python-format +msgid "" +"You can not delete this document (%s) ! Be sure your user belongs to one of " +"these groups: %s." +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_base_module_configuration +msgid "base.module.configuration" +msgstr "" + +#. module: base +#: field:base.language.export,name:0 +#: field:ir.attachment,datas_fname:0 +msgid "Filename" +msgstr "" + +#. module: base +#: field:ir.model,access_ids:0 +#: view:ir.model.access:0 +msgid "Access" +msgstr "" + +#. module: base +#: model:res.country,name:base.sk +msgid "Slovak Republic" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.publisher_warranty +msgid "Publisher Warranty" +msgstr "" + +#. module: base +#: model:res.country,name:base.aw +msgid "Aruba" +msgstr "" + +#. module: base +#: model:res.country,name:base.ar +msgid "Argentina" +msgstr "" + +#. module: base +#: field:res.groups,name:0 +msgid "Group Name" +msgstr "" + +#. module: base +#: model:res.country,name:base.bh +msgid "Bahrain" +msgstr "" + +#. module: base +#: model:res.partner.category,name:base.res_partner_category_12 +msgid "Segmentation" +msgstr "" + +#. module: base +#: view:ir.attachment:0 +#: field:ir.attachment,company_id:0 +#: field:ir.default,company_id:0 +#: field:ir.property,company_id:0 +#: field:ir.sequence,company_id:0 +#: field:ir.values,company_id:0 +#: view:res.company:0 +#: field:res.config.users,company_id:0 +#: field:res.currency,company_id:0 +#: field:res.partner,company_id:0 +#: field:res.partner.address,company_id:0 +#: view:res.users:0 +#: field:res.users,company_id:0 +msgid "Company" +msgstr "" + +#. module: base +#: view:res.users:0 +msgid "Email & Signature" +msgstr "" + +#. module: base +#: view:publisher_warranty.contract:0 +msgid "Publisher Warranty Contract" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Bulgarian / български език" +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_aftersale +msgid "After-Sale Services" +msgstr "" + +#. module: base +#: view:ir.actions.todo:0 +msgid "Launch" +msgstr "" + +#. module: base +#: field:ir.actions.act_window,limit:0 +msgid "Limit" +msgstr "" + +#. module: base +#: help:ir.actions.server,wkf_model_id:0 +msgid "Workflow to be executed on this model." +msgstr "" + +#. module: base +#: model:res.country,name:base.jm +msgid "Jamaica" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,help:base.action_partner_category_form +msgid "" +"Manage the partner categories in order to better classify them for tracking " +"and analysis purposes. A partner may belong to several categories and " +"categories have a hierarchy structure: a partner belonging to a category " +"also belong to his parent category." +msgstr "" + +#. module: base +#: model:res.country,name:base.az +msgid "Azerbaijan" +msgstr "" + +#. module: base +#: code:addons/base/res/partner/partner.py:250 +#, python-format +msgid "Warning" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Arabic / الْعَرَبيّة" +msgstr "" + +#. module: base +#: model:res.country,name:base.vg +msgid "Virgin Islands (British)" +msgstr "" + +#. module: base +#: view:ir.property:0 +#: model:ir.ui.menu,name:base.next_id_15 +msgid "Parameters" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Czech / Čeština" +msgstr "" + +#. module: base +#: view:ir.actions.server:0 +msgid "Trigger Configuration" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,help:base.action_partner_supplier_form +msgid "" +"You can access all information regarding your suppliers from the supplier " +"form: accounting data, history of emails, meetings, purchases, etc. You can " +"uncheck the 'Suppliers' filter button in order to search in all your " +"partners, including customers and prospects." +msgstr "" + +#. module: base +#: model:res.country,name:base.rw +msgid "Rwanda" +msgstr "" + +#. module: base +#: view:ir.sequence:0 +msgid "Day of the week (0:Monday): %(weekday)s" +msgstr "" + +#. module: base +#: model:res.country,name:base.ck +msgid "Cook Islands" +msgstr "" + +#. module: base +#: field:ir.model.data,noupdate:0 +msgid "Non Updatable" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Klingon" +msgstr "" + +#. module: base +#: model:res.country,name:base.sg +msgid "Singapore" +msgstr "" + +#. module: base +#: selection:ir.actions.act_window,target:0 +msgid "Current Window" +msgstr "" + +#. module: base +#: view:ir.values:0 +msgid "Action Source" +msgstr "" + +#. module: base +#: view:res.config.view:0 +msgid "" +"If you use OpenERP for the first time we strongly advise you to select the " +"simplified interface, which has less features but is easier. You can always " +"switch later from the user preferences." +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_country +#: field:res.bank,country:0 +#: view:res.country:0 +#: field:res.country.state,country_id:0 +#: field:res.partner,country:0 +#: view:res.partner.address:0 +#: field:res.partner.address,country_id:0 +#: field:res.partner.bank,country_id:0 +msgid "Country" +msgstr "" + +#. module: base +#: field:ir.model.fields,complete_name:0 +#: field:ir.ui.menu,complete_name:0 +msgid "Complete Name" +msgstr "" + +#. module: base +#: field:ir.values,object:0 +msgid "Is Object" +msgstr "" + +#. module: base +#: view:ir.rule:0 +msgid "" +"1. Global rules are combined together with a logical AND operator, and with " +"the result of the following steps" +msgstr "" + +#. module: base +#: field:res.partner.category,name:0 +msgid "Category Name" +msgstr "" + +#. module: base +#: model:res.partner.category,name:base.res_partner_category_15 +msgid "IT sector" +msgstr "" + +#. module: base +#: view:ir.actions.act_window:0 +msgid "Select Groups" +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "%X - Appropriate time representation." +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Spanish (SV) / Español (SV)" +msgstr "" + +#. module: base +#: help:res.lang,grouping:0 +msgid "" +"The Separator Format should be like [,n] where 0 < n :starting from Unit " +"digit.-1 will end the separation. e.g. [3,2,-1] will represent 106500 to be " +"1,06,500;[1,2,-1] will represent it to be 106,50,0;[3] will represent it as " +"106,500. Provided ',' as the thousand separator in each case." +msgstr "" + +#. module: base +#: view:res.company:0 +msgid "Portrait" +msgstr "" + +#. module: base +#: code:addons/base/ir/ir_model.py:317 +#, python-format +msgid "Can only rename one column at a time!" +msgstr "" + +#. module: base +#: selection:ir.translation,type:0 +msgid "Wizard Button" +msgstr "" + +#. module: base +#: selection:ir.translation,type:0 +msgid "Report/Template" +msgstr "" + +#. module: base +#: selection:ir.actions.act_window.view,view_mode:0 +#: selection:ir.ui.view,type:0 +#: selection:wizard.ir.model.menu.create.line,view_type:0 +msgid "Graph" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_ir_actions_server +#: selection:ir.ui.menu,action:0 +msgid "ir.actions.server" +msgstr "" + +#. module: base +#: field:ir.actions.configuration.wizard,progress:0 +#: field:res.config,progress:0 +#: field:res.config.installer,progress:0 +#: field:res.config.users,progress:0 +#: field:res.config.view,progress:0 +msgid "Configuration Progress" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.act_ir_actions_todo_form +#: model:ir.ui.menu,name:base.menu_ir_actions_todo_form +#: model:ir.ui.menu,name:base.next_id_11 +msgid "Configuration Wizards" +msgstr "" + +#. module: base +#: field:res.lang,code:0 +msgid "Locale Code" +msgstr "" + +#. module: base +#: field:workflow.activity,split_mode:0 +msgid "Split Mode" +msgstr "" + +#. module: base +#: view:base.module.upgrade:0 +msgid "Note that this operation might take a few minutes." +msgstr "" + +#. module: base +#: model:ir.ui.menu,name:base.menu_localisation +msgid "Localisation" +msgstr "" + +#. module: base +#: view:ir.actions.server:0 +msgid "Action to Launch" +msgstr "" + +#. module: base +#: view:ir.cron:0 +msgid "Execution" +msgstr "" + +#. module: base +#: field:ir.actions.server,condition:0 +#: field:workflow.transition,condition:0 +msgid "Condition" +msgstr "" + +#. module: base +#: help:ir.values,model_id:0 +msgid "This field is not used, it only helps you to select a good model." +msgstr "" + +#. module: base +#: field:ir.ui.view,name:0 +msgid "View Name" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Italian / Italiano" +msgstr "" + +#. module: base +#: field:ir.actions.report.xml,attachment:0 +msgid "Save As Attachment Prefix" +msgstr "" + +#. module: base +#: view:ir.actions.server:0 +msgid "" +"Only one client action will be executed, last client action will be " +"considered in case of multiple client actions." +msgstr "" + +#. module: base +#: view:res.lang:0 +msgid "%j - Day of the year [001,366]." +msgstr "" + +#. module: base +#: field:ir.actions.server,mobile:0 +msgid "Mobile No" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_partner_by_category +#: model:ir.actions.act_window,name:base.action_partner_category_form +#: model:ir.model,name:base.model_res_partner_category +#: model:ir.ui.menu,name:base.menu_partner_category_form +#: view:res.partner.category:0 +msgid "Partner Categories" +msgstr "" + +#. module: base +#: view:base.module.upgrade:0 +msgid "System Update" +msgstr "" + +#. module: base +#: selection:ir.translation,type:0 +msgid "Wizard Field" +msgstr "" + +#. module: base +#: help:ir.sequence,prefix:0 +msgid "Prefix value of the record for the sequence" +msgstr "" + +#. module: base +#: model:res.country,name:base.sc +msgid "Seychelles" +msgstr "" + +#. module: base +#: model:ir.model,name:base.model_res_partner_bank +#: view:res.partner.bank:0 +msgid "Bank Accounts" +msgstr "" + +#. module: base +#: model:res.country,name:base.sl +msgid "Sierra Leone" +msgstr "塞拉里昂" + +#. module: base +#: view:res.company:0 +#: view:res.partner:0 +msgid "General Information" +msgstr "" + +#. module: base +#: model:res.country,name:base.tc +msgid "Turks and Caicos Islands" +msgstr "" + +#. module: base +#: field:res.partner.bank,owner_name:0 +msgid "Account Owner" +msgstr "" + +#. module: base +#: code:addons/base/res/res_user.py:256 +#, python-format +msgid "Company Switch Warning" +msgstr "" + +#. module: base +#: model:ir.actions.act_window,name:base.action_res_widget_wizard +msgid "Homepage Widgets Management" +msgstr "" + +#. module: base +#: field:workflow,osv:0 +#: field:workflow.instance,res_type:0 +msgid "Resource Object" +msgstr "" + +#. module: base +#: help:ir.sequence,number_increment:0 +msgid "The next number of the sequence will be incremented by this number" +msgstr "" + +#. module: base +#: field:ir.cron,function:0 +#: field:res.partner.address,function:0 +#: selection:workflow.activity,kind:0 +msgid "Function" +msgstr "" + +#. module: base +#: view:res.widget:0 +msgid "Search Widget" +msgstr "" + +#. module: base +#: selection:ir.actions.todo,restart:0 +msgid "Never" +msgstr "" + +#. module: base +#: selection:res.partner.address,type:0 +msgid "Delivery" +msgstr "" + +#. module: base +#: model:res.partner.title,name:base.res_partner_title_pvt_ltd +#: model:res.partner.title,shortcut:base.res_partner_title_pvt_ltd +msgid "Corp." +msgstr "" + +#. module: base +#: model:res.country,name:base.gw +msgid "Guinea Bissau" +msgstr "" + +#. module: base +#: view:workflow.instance:0 +msgid "Workflow Instances" +msgstr "" + +#. module: base +#: code:addons/base/res/partner/partner.py:261 +#, python-format +msgid "Partners: " +msgstr "" + +#. module: base +#: model:res.country,name:base.kp +msgid "North Korea" +msgstr "" + +#. module: base +#: selection:ir.actions.server,state:0 +msgid "Create Object" +msgstr "" + +#. module: base +#: view:ir.filters:0 +#: field:res.log,context:0 +msgid "Context" +msgstr "" + +#. module: base +#: field:res.bank,bic:0 +msgid "BIC/Swift code" +msgstr "" + +#. module: base +#: model:res.partner.category,name:base.res_partner_category_1 +msgid "Prospect" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Polish / Język polski" +msgstr "" + +#. module: base +#: field:ir.exports,name:0 +msgid "Export Name" +msgstr "" + +#. module: base +#: help:res.partner.address,type:0 +msgid "" +"Used to select automatically the right address according to the context in " +"sales and purchases documents." +msgstr "" + +#. module: base +#: model:res.country,name:base.lk +msgid "Sri Lanka" +msgstr "" + +#. module: base +#: selection:base.language.install,lang:0 +msgid "Russian / русский язык" +msgstr "" diff --git a/openerp/addons/base/i18n/zh_TW.po b/openerp/addons/base/i18n/zh_TW.po index 76f346231dc..53610346f81 100644 --- a/openerp/addons/base/i18n/zh_TW.po +++ b/openerp/addons/base/i18n/zh_TW.po @@ -7,14 +7,14 @@ msgstr "" "Project-Id-Version: OpenERP Server 5.0.0\n" "Report-Msgid-Bugs-To: support@openerp.com\n" "POT-Creation-Date: 2011-01-11 11:14+0000\n" -"PO-Revision-Date: 2011-01-28 02:14+0000\n" +"PO-Revision-Date: 2011-09-27 16:28+0000\n" "Last-Translator: Walter Cheuk \n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-09-01 04:45+0000\n" -"X-Generator: Launchpad (build 13827)\n" +"X-Launchpad-Export-Date: 2011-09-28 05:19+0000\n" +"X-Generator: Launchpad (build 14049)\n" #. module: base #: view:ir.filters:0 @@ -46,7 +46,7 @@ msgstr "日期時間" msgid "" "The second argument of the many2many field %s must be a SQL table !You used " "%s, which is not a valid SQL table name." -msgstr "many2many 欄位 %s 之第二個引數須為 SQL 表格!您用了並非有效 SQL 表格名稱之 %s。" +msgstr "「多對多(many2many)」欄位 %s 之第二個引數須為 SQL 表格!您用了並非有效 SQL 表格名稱之 %s。" #. module: base #: view:ir.values:0 @@ -103,7 +103,7 @@ msgstr "工作流程作用於" #. module: base #: field:ir.actions.act_window,display_menu_tip:0 msgid "Display Menu Tips" -msgstr "顯示選表提示" +msgstr "顯示選單提示" #. module: base #: view:ir.module.module:0 @@ -129,7 +129,7 @@ msgstr "" #. module: base #: field:res.partner,ref:0 msgid "Reference" -msgstr "參照" +msgstr "參考" #. module: base #: field:ir.actions.act_window,target:0 @@ -154,7 +154,7 @@ msgstr "" #: code:addons/osv.py:133 #, python-format msgid "Constraint Error" -msgstr "" +msgstr "約束錯誤" #. module: base #: model:ir.model,name:base.model_ir_ui_view_custom @@ -171,12 +171,12 @@ msgstr "史瓦濟蘭" #: code:addons/orm.py:3653 #, python-format msgid "created." -msgstr "" +msgstr "已建立。" #. module: base #: model:res.partner.category,name:base.res_partner_category_woodsuppliers0 msgid "Wood Suppliers" -msgstr "" +msgstr "木材供應商" #. module: base #: code:addons/base/module/module.py:303 @@ -224,7 +224,7 @@ msgstr "新" #. module: base #: field:ir.actions.report.xml,multi:0 msgid "On multiple doc." -msgstr "作用於多重檔案。" +msgstr "作用於多重文件。" #. module: base #: field:ir.module.category,module_nr:0 @@ -252,12 +252,12 @@ msgstr "聯絡人名稱" msgid "" "Save this document to a %s file and edit it with a specific software or a " "text editor. The file encoding is UTF-8." -msgstr "將此檔案儲存為%s檔案後可以特定軟體或文字編輯程式修改。檔案編碼為 UTF-8。" +msgstr "將此檔案存為 %s 檔案,並以特定軟體或文字編輯程式修改。檔案編碼為 UTF-8。" #. module: base #: sql_constraint:res.lang:0 msgid "The name of the language must be unique !" -msgstr "" +msgstr "語言名稱須與其他不同 !" #. module: base #: selection:res.request,state:0 @@ -329,7 +329,7 @@ msgstr "欄位名稱" #: wizard_view:server.action.create,init:0 #: wizard_field:server.action.create,init,type:0 msgid "Select Action Type" -msgstr "選擇動作類型" +msgstr "選取動作類型" #. module: base #: model:res.country,name:base.tv @@ -422,7 +422,7 @@ msgstr "哥倫比亞" #. module: base #: view:ir.module.module:0 msgid "Schedule Upgrade" -msgstr "排程升級" +msgstr "安排升級" #. module: base #: code:addons/orm.py:838 @@ -436,7 +436,7 @@ msgid "" "The ISO country code in two chars.\n" "You can use this field for quick search." msgstr "" -"ISO 國家代碼使用兩個字符。\n" +"ISO 國家代碼使用兩個字元。\n" "您可以使用該欄位來快速搜索。" #. module: base @@ -447,7 +447,7 @@ msgstr "帛琉" #. module: base #: view:res.partner:0 msgid "Sales & Purchases" -msgstr "銷售&採購" +msgstr "銷售 及 購貨" #. module: base #: view:ir.translation:0 @@ -481,7 +481,7 @@ msgstr "自訂欄位名稱開頭必須是 'x_' !" #. module: base #: help:ir.actions.server,action_id:0 msgid "Select the Action Window, Report, Wizard to be executed." -msgstr "選擇要執行的動作視窗、報表或精靈。" +msgstr "選取要執行之動作視窗、報表或精靈。" #. module: base #: view:res.config.users:0 @@ -502,7 +502,7 @@ msgstr "模型說明" #: help:ir.actions.act_window,src_model:0 msgid "" "Optional model name of the objects on which this action should be visible" -msgstr "" +msgstr "要可見動作的物件之模型名稱(可有可無)" #. module: base #: field:workflow.transition,trigger_expr_id:0 @@ -548,7 +548,7 @@ msgstr "是否檢查 Ean? " #. module: base #: field:ir.values,key2:0 msgid "Event Type" -msgstr "事件類型" +msgstr "活動類型" #. module: base #: view:base.language.export:0 @@ -684,7 +684,7 @@ msgstr "西班牙文 (UY) / Español (UY)" #: field:res.partner,mobile:0 #: field:res.partner.address,mobile:0 msgid "Mobile" -msgstr "手機" +msgstr "手提電話" #. module: base #: model:res.country,name:base.om @@ -741,7 +741,7 @@ msgstr "印度" #: model:ir.actions.act_window,name:base.res_request_link-act #: model:ir.ui.menu,name:base.menu_res_request_link_act msgid "Request Reference Types" -msgstr "請求參照類型" +msgstr "請求參考類型" #. module: base #: view:ir.values:0 @@ -812,7 +812,7 @@ msgstr "人力資源儀錶板" #: code:addons/base/res/res_user.py:507 #, python-format msgid "Setting empty passwords is not allowed for security reasons!" -msgstr "因保安理由密碼不能留空!" +msgstr "因安全理由密碼不能留空!" #. module: base #: selection:ir.actions.server,state:0 @@ -882,7 +882,7 @@ msgstr "刪除存取" #. module: base #: model:res.country,name:base.ne msgid "Niger" -msgstr "尼日爾" +msgstr "尼日" #. module: base #: selection:base.language.install,lang:0 @@ -998,7 +998,7 @@ msgstr "儀錶板" #. module: base #: model:ir.ui.menu,name:base.menu_purchase_root msgid "Purchases" -msgstr "採購" +msgstr "購貨" #. module: base #: model:res.country,name:base.md @@ -1120,7 +1120,7 @@ msgstr "報表" msgid "" "If set to true, the action will not be displayed on the right toolbar of a " "form view." -msgstr "如設為是,該動作不會顯示於表單檢視右側工具欄。" +msgstr "如設為真,該動作不會顯示於表單檢視右側工具欄。" #. module: base #: field:workflow,on_create:0 @@ -1239,7 +1239,7 @@ msgstr "馬爾地夫" #. module: base #: help:ir.values,res_id:0 msgid "Keep 0 if the action must appear on all resources." -msgstr "如果該動作要顯示於所有資源上的話請保持為「0」。" +msgstr "如該動作要顯示於所有資源的話請保持為「0」。" #. module: base #: model:ir.model,name:base.model_ir_rule @@ -1325,7 +1325,7 @@ msgstr "優先次序" #. module: base #: field:workflow.transition,act_from:0 msgid "Source Activity" -msgstr "來源活動" +msgstr "來源地動態" #. module: base #: view:ir.sequence:0 @@ -1368,7 +1368,7 @@ msgstr "完整路徑" #. module: base #: view:res.request:0 msgid "References" -msgstr "參照" +msgstr "參考" #. module: base #: view:res.lang:0 @@ -1510,7 +1510,7 @@ msgstr "" #. module: base #: view:workflow.activity:0 msgid "Workflow Activity" -msgstr "工作流程活動" +msgstr "工作流程動態" #. module: base #: view:ir.rule:0 @@ -1694,7 +1694,7 @@ msgstr "原始檢視" #. module: base #: view:ir.values:0 msgid "Action To Launch" -msgstr "要啟動之動作" +msgstr "要執行之動作" #. module: base #: field:ir.actions.url,target:0 @@ -1736,7 +1736,7 @@ msgstr "" #. module: base #: help:ir.values,action_id:0 msgid "This field is not used, it only helps you to select the right action." -msgstr "該欄位並未使用,只是為了幫您選擇正確的動作。" +msgstr "此欄位並未使用,只是為了幫您選擇正確動作。" #. module: base #: field:ir.actions.server,email:0 @@ -1916,7 +1916,7 @@ msgstr "諾福克島" #. module: base #: selection:base.language.install,lang:0 msgid "Korean (KR) / 한국어 (KR)" -msgstr "韓文 (KR) / 한국어 (KR)" +msgstr "韓文 (北韓) / 한국어 (KR)" #. module: base #: help:ir.model.fields,model:0 @@ -1927,7 +1927,7 @@ msgstr "" #: field:ir.actions.server,action_id:0 #: selection:ir.actions.server,state:0 msgid "Client Action" -msgstr "客戶端動作" +msgstr "用戶端動作" #. module: base #: model:res.country,name:base.bd @@ -2007,7 +2007,7 @@ msgstr "屬性" #: model:ir.model,name:base.model_res_partner_bank_type #: view:res.partner.bank.type:0 msgid "Bank Account Type" -msgstr "銀行帳戶類型" +msgstr "銀行帳號類型" #. module: base #: field:base.language.export,config_logo:0 @@ -2171,7 +2171,7 @@ msgstr "西班牙文 (DO) / Español (DO)" #. module: base #: model:ir.model,name:base.model_workflow_activity msgid "workflow.activity" -msgstr "工作流程.活動" +msgstr "工作流程.動態" #. module: base #: help:ir.ui.view_sc,res_id:0 @@ -2239,7 +2239,7 @@ msgstr "" #. module: base #: field:ir.default,ref_id:0 msgid "ID Ref." -msgstr "ID參照" +msgstr "ID參考" #. module: base #: model:ir.actions.server,name:base.action_start_configurator @@ -2313,7 +2313,7 @@ msgstr "分格格式" #. module: base #: selection:publisher_warranty.contract,state:0 msgid "Unvalidated" -msgstr "未檢驗" +msgstr "未驗證" #. module: base #: model:ir.ui.menu,name:base.next_id_9 @@ -2336,7 +2336,7 @@ msgstr "馬約特" #: code:addons/base/ir/ir_actions.py:597 #, python-format msgid "Please specify an action to launch !" -msgstr "請指定執行動作!" +msgstr "請指定要執行之動作!" #. module: base #: view:res.payterm:0 @@ -2368,7 +2368,7 @@ msgstr "請檢查所有行數皆有%d個欄位。" #: view:ir.cron:0 #: model:ir.ui.menu,name:base.menu_ir_cron_act msgid "Scheduled Actions" -msgstr "計劃的動作" +msgstr "已安排動作" #. module: base #: field:res.partner.address,title:0 @@ -2412,7 +2412,7 @@ msgstr "建立選單" msgid "" "Value Added Tax number. Check the box if the partner is subjected to the " "VAT. Used by the VAT legal statement." -msgstr "增值稅編號。如該伙伴適用於增值稅,請選擇。用於增值稅申報。" +msgstr "增值稅編號。如該伙伴需要繳交增值稅,請選擇。用於申報增值稅。" #. module: base #: model:ir.model,name:base.model_maintenance_contract @@ -2710,7 +2710,7 @@ msgstr "基礎欄位" #. module: base #: view:publisher_warranty.contract:0 msgid "Validate" -msgstr "檢驗" +msgstr "驗證" #. module: base #: field:ir.actions.todo,restart:0 @@ -2810,7 +2810,7 @@ msgstr "" #. module: base #: model:res.partner.category,name:base.res_partner_category_16 msgid "Telecom sector" -msgstr "電訊範疇" +msgstr "電信範疇" #. module: base #: field:workflow.transition,trigger_model:0 @@ -2820,7 +2820,7 @@ msgstr "觸發器物件" #. module: base #: view:res.users:0 msgid "Current Activity" -msgstr "目前活動" +msgstr "當前動態" #. module: base #: view:workflow.activity:0 @@ -2842,7 +2842,7 @@ msgstr "行銷" #: view:res.partner.bank:0 #: model:res.partner.bank.type,name:base.bank_normal msgid "Bank account" -msgstr "銀行帳戶" +msgstr "銀行帳號" #. module: base #: selection:base.language.install,lang:0 @@ -2857,7 +2857,7 @@ msgstr "序列類型" #. module: base #: view:ir.ui.view.custom:0 msgid "Customized Architecture" -msgstr "自訂架構" +msgstr "自訂化架構" #. module: base #: field:ir.module.module,license:0 @@ -2877,7 +2877,7 @@ msgstr "必定" #. module: base #: selection:ir.translation,type:0 msgid "SQL Constraint" -msgstr "SQL 限制" +msgstr "SQL 約束" #. module: base #: field:ir.actions.server,srcmodel_id:0 @@ -3070,7 +3070,7 @@ msgstr "肯亞" #. module: base #: view:res.partner.event:0 msgid "Event" -msgstr "事件" +msgstr "活動" #. module: base #: model:ir.ui.menu,name:base.menu_custom_reports @@ -3080,7 +3080,7 @@ msgstr "自訂報表" #. module: base #: selection:base.language.install,lang:0 msgid "Abkhazian / аҧсуа" -msgstr "阿布哈茲文 / аҧсуа" +msgstr "阿布哈兹文 / аҧсуа" #. module: base #: view:base.module.configuration:0 @@ -3106,7 +3106,7 @@ msgstr "聖馬利諾" #. module: base #: model:res.country,name:base.bm msgid "Bermuda" -msgstr "百慕達" +msgstr "百慕大" #. module: base #: model:res.country,name:base.pe @@ -3180,7 +3180,7 @@ msgstr "完整存取" #: view:ir.model.fields:0 #: model:ir.ui.menu,name:base.menu_security msgid "Security" -msgstr "保安" +msgstr "安全" #. module: base #: model:res.widget,title:base.openerp_favorites_twitter_widget @@ -3481,8 +3481,8 @@ msgid "" "plugin, don't forget to register emails to each contact so that the gateway " "will automatically attach incoming emails to the right partner." msgstr "" -"客戶是指您與其做生意者,例如公司或機構。客戶可有多個聯絡人或地址,均屬於其員工。您可用「歷史」分頁追蹤所有有關交易:訂單、電郵、機會、退款要求等等。如您用" -"電郵閘道和 Outlook 或 Thunderbird 外掛程式,別忘了為聯絡人登記電郵,好讓閘道自動為合適伙伴寄送收到之電郵。" +"客戶是指您與其做生意者,例如公司或機構。客戶可有多個聯絡人或地址,均屬於其員工。您可用「歷史」分頁追蹤所有有關交易:訂單、電郵、商機、退款要求等等。如您用" +"電郵閘道、Outlook 或 Thunderbird 外掛程式,別忘了為聯絡人登記電郵,好讓閘道自動為合適伙伴寄送收到之電郵。" #. module: base #: field:ir.actions.report.xml,name:0 @@ -3517,7 +3517,7 @@ msgstr "名稱" msgid "" "If set to true, the action will not be displayed on the right toolbar of a " "form view" -msgstr "如設為是,該動作不會顯示於表單檢視右側工具欄" +msgstr "如設為真,該動作不會顯示於表單檢視右側工具欄" #. module: base #: model:res.country,name:base.ms @@ -3543,7 +3543,7 @@ msgstr "應用程式詞彙" msgid "" "The user's timezone, used to perform timezone conversions between the server " "and the client." -msgstr "" +msgstr "用戶之時區,用以為伺服器及用戶端進行時區轉換。" #. module: base #: field:ir.module.module,demo:0 @@ -3565,7 +3565,7 @@ msgstr "日文 / 日本語" msgid "" "Source activity. When this activity is over, the condition is tested to " "determine if we can start the ACT_TO activity." -msgstr "" +msgstr "來源地動態。當再無動態,會測試條件以決定是否開始 ACT_TO 動態。" #. module: base #: model:res.partner.category,name:base.res_partner_category_3 @@ -3618,7 +3618,7 @@ msgstr "冷岸及央麥恩群島" #: model:ir.model,name:base.model_ir_actions_wizard #: selection:ir.ui.menu,action:0 msgid "ir.actions.wizard" -msgstr "" +msgstr "ir.actions.wizard" #. module: base #: view:ir.actions.act_window:0 @@ -3753,12 +3753,12 @@ msgstr "無法載入模組基礎!(提示:檢查附加元件路徑)" #. module: base #: view:res.partner.bank:0 msgid "Bank Account Owner" -msgstr "銀行帳戶所有者" +msgstr "銀行帳號所有者" #. module: base #: model:ir.actions.act_window,name:base.act_values_form msgid "Client Actions Connections" -msgstr "客戶端動作連接" +msgstr "用戶端動作連線" #. module: base #: field:ir.attachment,res_name:0 @@ -3836,7 +3836,7 @@ msgstr "" #. module: base #: view:ir.actions.server:0 msgid "Client Action Configuration" -msgstr "客戶端動作設置" +msgstr "用戶端動作設定" #. module: base #: model:ir.model,name:base.model_res_partner_address @@ -3872,13 +3872,13 @@ msgstr "選取要匯入之模組套件 (.zip 檔):" #: field:res.partner.event,name:0 #: model:res.widget,title:base.events_widget msgid "Events" -msgstr "事件" +msgstr "活動" #. module: base #: model:ir.model,name:base.model_ir_actions_url #: selection:ir.ui.menu,action:0 msgid "ir.actions.url" -msgstr "" +msgstr "ir.actions.url" #. module: base #: model:res.widget,title:base.currency_converter_widget @@ -4098,7 +4098,7 @@ msgstr "重複錯過的" #. module: base #: help:ir.actions.server,state:0 msgid "Type of the Action that is to be executed" -msgstr "將要執行動作之類型" +msgstr "要執行動作之類型" #. module: base #: field:ir.server.object.lines,server_id:0 @@ -4706,7 +4706,7 @@ msgid "" "Track from where is coming your leads and opportunities by creating specific " "channels that will be maintained at the creation of a document in the " "system. Some examples of channels can be: Website, Phone Call, Reseller, etc." -msgstr "" +msgstr "於系統建立文件,以保持特定渠道追蹤潛在客戶及商機之來源。渠道例子有網站、電話查詢、零售商等等。" #. module: base #: model:res.partner.bank.type.field,name:base.bank_normal_field @@ -4765,7 +4765,7 @@ msgstr "變改我的偏好設定" #: code:addons/base/ir/ir_actions.py:164 #, python-format msgid "Invalid model name in the action definition." -msgstr "動作定義之模型名無效。" +msgstr "動作定義之模型名稱無效。" #. module: base #: field:partner.sms.send,text:0 @@ -4900,7 +4900,7 @@ msgstr "如指定,此動作會於此用戶登入時於標準選單以外額外 #. module: base #: view:ir.values:0 msgid "Client Actions" -msgstr "客戶端動作" +msgstr "用戶端動作" #. module: base #: code:addons/orm.py:1806 @@ -4921,12 +4921,12 @@ msgstr "" #. module: base #: field:workflow.transition,act_to:0 msgid "Destination Activity" -msgstr "目的地活動" +msgstr "目的地動態" #. module: base #: view:ir.values:0 msgid "Connect Events to Actions" -msgstr "把事件連接動作" +msgstr "把活動關聯到動作" #. module: base #: model:ir.model,name:base.model_base_update_translations @@ -5041,7 +5041,7 @@ msgstr "網頁圖示影像" #. module: base #: view:ir.values:0 msgid "Values for Event Type" -msgstr "事件類型值" +msgstr "活動類型值" #. module: base #: selection:ir.model.fields,select_level:0 @@ -5069,6 +5069,8 @@ msgid "" "installed the CRM, with the history tab, you can track all the interactions " "with a partner such as opportunities, emails, or sales orders issued." msgstr "" +"客戶(於系統其他地方又稱「伙伴」)助您管理其他公司,包括潛在客戶、客戶及/或供應商,之通訊錄。「伙伴表單」讓您追蹤及紀錄所有所需資訊,以讓您處理公司地址、" +"聯絡人、報價單等等。如您安裝了客戶關係管理(CRM)模組,以歷史分頁您可追蹤與伙伴有關之所有來往,如商機、電郵或銷售訂單等。" #. module: base #: model:res.country,name:base.ph @@ -5552,7 +5554,7 @@ msgstr "" #: code:addons/base/res/res_config.py:94 #, python-format msgid "Couldn't find previous ir.actions.todo" -msgstr "" +msgstr "找不到之前的 ir.actions.todo" #. module: base #: view:ir.actions.act_window:0 @@ -5792,7 +5794,7 @@ msgstr "宏都拉斯" #: help:res.users,menu_tips:0 msgid "" "Check out this box if you want to always display tips on each menu action" -msgstr "" +msgstr "如想於每個選單動作顯示提示,勾選此框" #. module: base #: model:res.country,name:base.eg @@ -6078,7 +6080,7 @@ msgstr "建立日期" msgid "" "Select the action that will be executed. Loop action will not be avaliable " "inside loop." -msgstr "選擇將要執行的動作。循環動作在循環內不可用。" +msgstr "選取要執行之動作。循環動作在循環內不可用。" #. module: base #: selection:base.language.install,lang:0 @@ -6358,7 +6360,7 @@ msgstr "模組更新結果" #: view:workflow.activity:0 #: field:workflow.workitem,act_id:0 msgid "Activity" -msgstr "活動" +msgstr "動態" #. module: base #: view:res.partner:0 @@ -6423,7 +6425,7 @@ msgstr "" msgid "" "Customized views are used when users reorganize the content of their " "dashboard views (via web client)" -msgstr "" +msgstr "當用戶(以 web client)重組其 dashboard 檢視即會使用自訂化檢視" #. module: base #: field:ir.model,name:0 @@ -6494,7 +6496,7 @@ msgstr "" #: model:ir.actions.act_window,name:base.res_log_act_window #: model:ir.ui.menu,name:base.menu_res_log_act_window msgid "Client Logs" -msgstr "客戶端日誌" +msgstr "用戶端日誌" #. module: base #: model:res.country,name:base.al @@ -6534,7 +6536,7 @@ msgstr "" #: code:addons/base/ir/ir_actions.py:716 #, python-format msgid "Problem in configuration `Record Id` in Server Action!" -msgstr "於伺服器動作之「Record Id」配置錯誤!" +msgstr "伺服器動作之「紀錄 Id」配置有問題!" #. module: base #: code:addons/orm.py:2306 @@ -6587,7 +6589,7 @@ msgstr "電郵" #: field:res.config.users,action_id:0 #: field:res.users,action_id:0 msgid "Home Action" -msgstr "家動作(Home Action)" +msgstr "家動作(Home Action)" #. module: base #: code:addons/custom.py:558 @@ -7603,7 +7605,7 @@ msgstr "要更新模組" msgid "" "Important when you deal with multiple actions, the execution order will be " "decided based on this, low number is higher priority." -msgstr "對於處理多個動作很重要,其決定動作執行順序;小的數字具較高優先次序。" +msgstr "對於處理多重動作很重要,其決定動作執行次序;小的數字具較高優先次序。" #. module: base #: field:ir.actions.report.xml,header:0 @@ -7756,7 +7758,7 @@ msgstr "格陵蘭" #. module: base #: field:res.partner.bank,acc_number:0 msgid "Account Number" -msgstr "帳戶號碼" +msgstr "帳號" #. module: base #: view:res.lang:0 @@ -7969,7 +7971,7 @@ msgstr "斯洛伐克文 / Slovenský jazyk" #: field:ir.ui.menu,icon_pict:0 #: field:publisher_warranty.contract.wizard,state:0 msgid "unknown" -msgstr "不明" +msgstr "不詳" #. module: base #: field:res.currency,symbol:0 @@ -8032,7 +8034,7 @@ msgstr "CSV 檔" #. module: base #: field:res.company,account_no:0 msgid "Account No." -msgstr "帳戶號碼" +msgstr "帳號" #. module: base #: code:addons/base/res/res_lang.py:157 @@ -8128,7 +8130,7 @@ msgstr "土耳其文 / Türkçe" #: view:workflow:0 #: field:workflow,activities:0 msgid "Activities" -msgstr "活動" +msgstr "動態" #. module: base #: field:ir.actions.act_window,auto_refresh:0 @@ -8166,7 +8168,7 @@ msgstr "" #: model:ir.ui.menu,name:base.menu_event_association #: model:ir.ui.menu,name:base.menu_event_main msgid "Events Organisation" -msgstr "事件組織" +msgstr "活動組織" #. module: base #: model:ir.actions.act_window,name:base.ir_sequence_actions @@ -8247,7 +8249,7 @@ msgstr "添加公司 RML 頁首與否" #. module: base #: help:workflow.transition,act_to:0 msgid "The destination activity." -msgstr "目的地活地。" +msgstr "目的地動態。" #. module: base #: view:base.module.update:0 @@ -8283,7 +8285,7 @@ msgstr "聖誕島" #. module: base #: view:ir.actions.server:0 msgid "Other Actions Configuration" -msgstr "其他動作設置" +msgstr "其他動作配置" #. module: base #: view:res.config.installer:0 @@ -8307,7 +8309,7 @@ msgstr "額外資訊" #: model:ir.actions.act_window,name:base.act_values_form_action #: model:ir.ui.menu,name:base.menu_values_form_action msgid "Client Events" -msgstr "客戶端事件" +msgstr "用戶端活動" #. module: base #: view:ir.module.module:0 @@ -8429,7 +8431,7 @@ msgstr "關聯欄位" #. module: base #: view:res.partner.event:0 msgid "Event Logs" -msgstr "事件日誌" +msgstr "活動日誌" #. module: base #: code:addons/base/module/wizard/base_module_configuration.py:37 @@ -8446,7 +8448,7 @@ msgstr "目的地實例" #: field:ir.actions.act_window,multi:0 #: field:ir.actions.wizard,multi:0 msgid "Action on Multiple Doc." -msgstr "動作作用於多個文件" +msgstr "多重文件之動作。" #. module: base #: view:base.language.export:0 @@ -8477,7 +8479,7 @@ msgstr "盧森堡" #: help:ir.values,key2:0 msgid "" "The kind of action or button in the client side that will trigger the action." -msgstr "客戶端的該類動作或按鈕將觸發此動作。" +msgstr "用戶端的該類動作或按鈕會觸發此動作。" #. module: base #: code:addons/base/ir/ir_ui_menu.py:285 @@ -8899,7 +8901,7 @@ msgstr "目前視窗" #. module: base #: view:ir.values:0 msgid "Action Source" -msgstr "動作來源" +msgstr "動作來源地" #. module: base #: view:res.config.view:0 @@ -9048,7 +9050,7 @@ msgstr "本地化" #. module: base #: view:ir.actions.server:0 msgid "Action to Launch" -msgstr "要啟動動作" +msgstr "要執行之動作" #. module: base #: view:ir.cron:0 @@ -9086,7 +9088,7 @@ msgstr "另存為附件前綴" msgid "" "Only one client action will be executed, last client action will be " "considered in case of multiple client actions." -msgstr "只能執行一個客戶端動作,如有多重動作只考慮最後一個。" +msgstr "只會執行一個用戶端動作,如有多重用戶端動作只考慮最後一個。" #. module: base #: view:res.lang:0 @@ -9131,7 +9133,7 @@ msgstr "塞席爾" #: model:ir.model,name:base.model_res_partner_bank #: view:res.partner.bank:0 msgid "Bank Accounts" -msgstr "銀行帳戶" +msgstr "銀行帳號" #. module: base #: model:res.country,name:base.sl @@ -9152,7 +9154,7 @@ msgstr "土克斯及開科斯群島" #. module: base #: field:res.partner.bank,owner_name:0 msgid "Account Owner" -msgstr "帳戶所有者" +msgstr "帳號所有者" #. module: base #: code:addons/base/res/res_user.py:256 diff --git a/openerp/addons/base/ir/ir.xml b/openerp/addons/base/ir/ir.xml index 966d3d8667a..2792259773d 100644 --- a/openerp/addons/base/ir/ir.xml +++ b/openerp/addons/base/ir/ir.xml @@ -1274,7 +1274,7 @@ - Objects + Models ir.model form {'manual':True} @@ -1740,7 +1740,7 @@ Property multi-company - ['|',('company_id','=',user.company_id.id),('company_id','=',False)] + ['|',('company_id','child_of',[user.company_id.id]),('company_id','=',False)] @@ -1766,7 +1766,9 @@ - + diff --git a/openerp/addons/base/ir/ir_actions.py b/openerp/addons/base/ir/ir_actions.py index 3442ecdc051..a2e107e741e 100644 --- a/openerp/addons/base/ir/ir_actions.py +++ b/openerp/addons/base/ir/ir_actions.py @@ -438,14 +438,15 @@ server_object_lines() class actions_server(osv.osv): def _select_signals(self, cr, uid, context=None): - cr.execute("SELECT distinct w.osv, t.signal FROM wkf w, wkf_activity a, wkf_transition t \ - WHERE w.id = a.wkf_id AND t.act_from = a.id OR t.act_to = a.id AND t.signal!='' \ - AND t.signal NOT IN (null, NULL)") + cr.execute("""SELECT distinct w.osv, t.signal FROM wkf w, wkf_activity a, wkf_transition t + WHERE w.id = a.wkf_id AND + (t.act_from = a.id OR t.act_to = a.id) AND + t.signal IS NOT NULL""") result = cr.fetchall() or [] res = [] for rs in result: if rs[0] is not None and rs[1] is not None: - line = rs[0], "%s - (%s)" % (rs[1], rs[0]) + line = rs[1], "%s - (%s)" % (rs[1], rs[0]) res.append(line) return res @@ -456,13 +457,15 @@ class actions_server(osv.osv): return [(r['model'], r['name']) for r in res] + [('','')] def change_object(self, cr, uid, ids, copy_object, state, context=None): - if state == 'object_copy': + if state == 'object_copy' and copy_object: + if context is None: + context = {} model_pool = self.pool.get('ir.model') model = copy_object.split(',')[0] mid = model_pool.search(cr, uid, [('model','=',model)]) return { - 'value':{'srcmodel_id':mid[0]}, - 'context':context + 'value': {'srcmodel_id': mid[0]}, + 'context': context } else: return {} @@ -503,9 +506,9 @@ class actions_server(osv.osv): 'sequence': fields.integer('Sequence', help="Important when you deal with multiple actions, the execution order will be decided based on this, low number is higher priority."), 'model_id': fields.many2one('ir.model', 'Object', required=True, help="Select the object on which the action will work (read, write, create)."), 'action_id': fields.many2one('ir.actions.actions', 'Client Action', help="Select the Action Window, Report, Wizard to be executed."), - 'trigger_name': fields.selection(_select_signals, string='Trigger Name', size=128, help="Select the Signal name that is to be used as the trigger."), - 'wkf_model_id': fields.many2one('ir.model', 'Workflow On', help="Workflow to be executed on this model."), - 'trigger_obj_id': fields.many2one('ir.model.fields','Trigger On', help="Select the object from the model on which the workflow will executed."), + 'trigger_name': fields.selection(_select_signals, string='Trigger Signal', size=128, help="The workflow signal to trigger"), + 'wkf_model_id': fields.many2one('ir.model', 'Target Object', help="The object that should receive the workflow signal (must have an associated workflow)"), + 'trigger_obj_id': fields.many2one('ir.model.fields','Relation Field', help="The field on the current object that links to the target object record (must be a many2one, or an integer field with the record ID)"), 'email': fields.char('Email Address', size=512, help="Expression that returns the email address to send to. Can be based on the same values as for the condition field.\n" "Example: object.invoice_address_id.email, or 'me@example.com'"), 'subject': fields.char('Subject', size=1024, translate=True, help="Email subject, may contain expressions enclosed in double brackets based on the same values as those " @@ -532,7 +535,7 @@ class actions_server(osv.osv): 'sequence': lambda *a: 5, 'code': lambda *a: """# You can use the following variables: # - self: ORM model of the record on which the action is triggered -# - object or obj: browse_record of the record on which the action is triggered +# - object: browse_record of the record on which the action is triggered if there is one, otherwise None # - pool: ORM model pool (i.e. self.pool) # - time: Python time module # - cr: database cursor @@ -685,9 +688,10 @@ class actions_server(osv.osv): if action.state == 'trigger': wf_service = netsvc.LocalService("workflow") model = action.wkf_model_id.model - res_id = obj_pool.read(cr, uid, [context.get('active_id')], [action.trigger_obj_id.name]) - id = res_id [0][action.trigger_obj_id.name] - wf_service.trg_validate(uid, model, int(id), action.trigger_name, cr) + m2o_field_name = action.trigger_obj_id.name + target_id = obj_pool.read(cr, uid, context.get('active_id'), [m2o_field_name])[m2o_field_name] + target_id = target_id[0] if isinstance(target_id,tuple) else target_id + wf_service.trg_validate(uid, model, int(target_id), action.trigger_name, cr) if action.state == 'sms': #TODO: set the user and password from the system diff --git a/openerp/addons/base/ir/ir_cron.py b/openerp/addons/base/ir/ir_cron.py index 054a15257ef..af46b0ef3e0 100644 --- a/openerp/addons/base/ir/ir_cron.py +++ b/openerp/addons/base/ir/ir_cron.py @@ -21,13 +21,20 @@ import time import logging +import threading +import psycopg2 from datetime import datetime from dateutil.relativedelta import relativedelta + import netsvc -import tools -from tools.safe_eval import safe_eval as eval +import openerp import pooler +import tools +from openerp.cron import WAKE_UP_NOW from osv import fields, osv +from tools import DEFAULT_SERVER_DATETIME_FORMAT +from tools.safe_eval import safe_eval as eval +from tools.translate import _ def str2tuple(s): return eval('tuple(%s)' % (s or '')) @@ -41,10 +48,15 @@ _intervalTypes = { 'minutes': lambda interval: relativedelta(minutes=interval), } -class ir_cron(osv.osv, netsvc.Agent): - """ This is the ORM object that periodically executes actions. - Note that we use the netsvc.Agent()._logger member. +class ir_cron(osv.osv): + """ Model describing cron jobs (also called actions or tasks). """ + + # TODO: perhaps in the future we could consider a flag on ir.cron jobs + # that would cause database wake-up even if the database has not been + # loaded yet or was already unloaded (e.g. 'force_db_wakeup' or something) + # See also openerp.cron + _name = "ir.cron" _order = 'name' _columns = { @@ -54,17 +66,17 @@ class ir_cron(osv.osv, netsvc.Agent): 'interval_number': fields.integer('Interval Number',help="Repeat every x."), 'interval_type': fields.selection( [('minutes', 'Minutes'), ('hours', 'Hours'), ('work_days','Work Days'), ('days', 'Days'),('weeks', 'Weeks'), ('months', 'Months')], 'Interval Unit'), - 'numbercall': fields.integer('Number of Calls', help='Number of time the function is called,\na negative number indicates no limit'), - 'doall' : fields.boolean('Repeat Missed', help="Enable this if you want to execute missed occurences as soon as the server restarts."), - 'nextcall' : fields.datetime('Next Execution Date', required=True, help="Next planned execution date for this scheduler"), - 'model': fields.char('Object', size=64, help="Name of object whose function will be called when this scheduler will run. e.g. 'res.partener'"), - 'function': fields.char('Function', size=64, help="Name of the method to be called on the object when this scheduler is executed."), - 'args': fields.text('Arguments', help="Arguments to be passed to the method. e.g. (uid,)"), - 'priority': fields.integer('Priority', help='0=Very Urgent\n10=Not urgent') + 'numbercall': fields.integer('Number of Calls', help='How many times the method is called,\na negative number indicates no limit.'), + 'doall' : fields.boolean('Repeat Missed', help="Specify if missed occurrences should be executed when the server restarts."), + 'nextcall' : fields.datetime('Next Execution Date', required=True, help="Next planned execution date for this job."), + 'model': fields.char('Object', size=64, help="Model name on which the method to be called is located, e.g. 'res.partner'."), + 'function': fields.char('Method', size=64, help="Name of the method to be called when this job is processed."), + 'args': fields.text('Arguments', help="Arguments to be passed to the method, e.g. (uid,)."), + 'priority': fields.integer('Priority', help='The priority of the job, as an integer: 0 means higher priority, 10 means lower priority.') } _defaults = { - 'nextcall' : lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'), + 'nextcall' : lambda *a: time.strftime(DEFAULT_SERVER_DATETIME_FORMAT), 'priority' : lambda *a: 5, 'user_id' : lambda obj,cr,uid,context: uid, 'interval_number' : lambda *a: 1, @@ -74,6 +86,8 @@ class ir_cron(osv.osv, netsvc.Agent): 'doall' : lambda *a: 1 } + _logger = logging.getLogger('cron') + def _check_args(self, cr, uid, ids, context=None): try: for this in self.browse(cr, uid, ids, context): @@ -86,68 +100,164 @@ class ir_cron(osv.osv, netsvc.Agent): (_check_args, 'Invalid arguments', ['args']), ] - def _handle_callback_exception(self, cr, uid, model, func, args, job_id, job_exception): - cr.rollback() - logger=logging.getLogger('cron') - logger.exception("Call of self.pool.get('%s').%s(cr, uid, *%r) failed in Job %s" % (model, func, args, job_id)) + def _handle_callback_exception(self, cr, uid, model_name, method_name, args, job_id, job_exception): + """ Method called when an exception is raised by a job. - def _callback(self, cr, uid, model, func, args, job_id): + Simply logs the exception and rollback the transaction. + + :param model_name: model name on which the job method is located. + :param method_name: name of the method to call when this job is processed. + :param args: arguments of the method (without the usual self, cr, uid). + :param job_id: job id. + :param job_exception: exception raised by the job. + + """ + cr.rollback() + self._logger.exception("Call of self.pool.get('%s').%s(cr, uid, *%r) failed in Job %s" % (model_name, method_name, args, job_id)) + + def _callback(self, cr, uid, model_name, method_name, args, job_id): + """ Run the method associated to a given job + + It takes care of logging and exception handling. + + :param model_name: model name on which the job method is located. + :param method_name: name of the method to call when this job is processed. + :param args: arguments of the method (without the usual self, cr, uid). + :param job_id: job id. + """ args = str2tuple(args) - m = self.pool.get(model) - if m and hasattr(m, func): - f = getattr(m, func) + model = self.pool.get(model_name) + if model and hasattr(model, method_name): + method = getattr(model, method_name) try: - netsvc.log('cron', (cr.dbname,uid,'*',model,func)+tuple(args), channel=logging.DEBUG, + netsvc.log('cron', (cr.dbname,uid,'*',model_name,method_name)+tuple(args), channel=logging.DEBUG, depth=(None if self._logger.isEnabledFor(logging.DEBUG_RPC_ANSWER) else 1), fn='object.execute') logger = logging.getLogger('execution time') if logger.isEnabledFor(logging.DEBUG): start_time = time.time() - f(cr, uid, *args) + method(cr, uid, *args) if logger.isEnabledFor(logging.DEBUG): end_time = time.time() - logger.log(logging.DEBUG, '%.3fs (%s, %s)' % (end_time - start_time, model, func)) + logger.log(logging.DEBUG, '%.3fs (%s, %s)' % (end_time - start_time, model_name, method_name)) except Exception, e: - self._handle_callback_exception(cr, uid, model, func, args, job_id, e) + self._handle_callback_exception(cr, uid, model_name, method_name, args, job_id, e) - def _poolJobs(self, db_name, check=False): + def _run_job(self, cr, job, now): + """ Run a given job taking care of the repetition. + + The cursor has a lock on the job (aquired by _run_jobs_multithread()) and this + method is run in a worker thread (spawned by _run_jobs_multithread())). + + :param job: job to be run (as a dictionary). + :param now: timestamp (result of datetime.now(), no need to call it multiple time). + + """ try: - db, pool = pooler.get_db_and_pool(db_name) - except: - return False + nextcall = datetime.strptime(job['nextcall'], DEFAULT_SERVER_DATETIME_FORMAT) + numbercall = job['numbercall'] + + ok = False + while nextcall < now and numbercall: + if numbercall > 0: + numbercall -= 1 + if not ok or job['doall']: + self._callback(cr, job['user_id'], job['model'], job['function'], job['args'], job['id']) + if numbercall: + nextcall += _intervalTypes[job['interval_type']](job['interval_number']) + ok = True + addsql = '' + if not numbercall: + addsql = ', active=False' + cr.execute("UPDATE ir_cron SET nextcall=%s, numbercall=%s"+addsql+" WHERE id=%s", + (nextcall.strftime(DEFAULT_SERVER_DATETIME_FORMAT), numbercall, job['id'])) + + if numbercall: + # Reschedule our own main cron thread if necessary. + # This is really needed if this job runs longer than its rescheduling period. + nextcall = time.mktime(nextcall.timetuple()) + openerp.cron.schedule_wakeup(nextcall, cr.dbname) + finally: + cr.commit() + cr.close() + openerp.cron.release_thread_slot() + + def _run_jobs_multithread(self): + # TODO remove 'check' argument from addons/base_action_rule/base_action_rule.py + """ Process the cron jobs by spawning worker threads. + + This selects in database all the jobs that should be processed. It then + tries to lock each of them and, if it succeeds, spawns a thread to run + the cron job (if it doesn't succeed, it means the job was already + locked to be taken care of by another thread). + + The cursor used to lock the job in database is given to the worker + thread (which has to close it itself). + + """ + db = self.pool.db cr = db.cursor() + db_name = db.dbname try: - if not pool._init: - now = datetime.now() - cr.execute('select * from ir_cron where numbercall<>0 and active and nextcall<=now() order by priority') - for job in cr.dictfetchall(): - nextcall = datetime.strptime(job['nextcall'], '%Y-%m-%d %H:%M:%S') - numbercall = job['numbercall'] + jobs = {} # mapping job ids to jobs for all jobs being processed. + now = datetime.now() + # Careful to compare timestamps with 'UTC' - everything is UTC as of v6.1. + cr.execute("""SELECT * FROM ir_cron + WHERE numbercall != 0 + AND active AND nextcall <= (now() at time zone 'UTC') + ORDER BY priority""") + for job in cr.dictfetchall(): + if not openerp.cron.get_thread_slots(): + break + jobs[job['id']] = job - ok = False - while nextcall < now and numbercall: - if numbercall > 0: - numbercall -= 1 - if not ok or job['doall']: - self._callback(cr, job['user_id'], job['model'], job['function'], job['args'], job['id']) - if numbercall: - nextcall += _intervalTypes[job['interval_type']](job['interval_number']) - ok = True - addsql = '' - if not numbercall: - addsql = ', active=False' - cr.execute("update ir_cron set nextcall=%s, numbercall=%s"+addsql+" where id=%s", (nextcall.strftime('%Y-%m-%d %H:%M:%S'), numbercall, job['id'])) - cr.commit() + task_cr = db.cursor() + try: + # Try to grab an exclusive lock on the job row from within the task transaction + acquired_lock = False + task_cr.execute("""SELECT * + FROM ir_cron + WHERE id=%s + FOR UPDATE NOWAIT""", + (job['id'],), log_exceptions=False) + acquired_lock = True + except psycopg2.OperationalError, e: + if e.pgcode == '55P03': + # Class 55: Object not in prerequisite state; 55P03: lock_not_available + self._logger.debug('Another process/thread is already busy executing job `%s`, skipping it.', job['name']) + continue + else: + # Unexpected OperationalError + raise + finally: + if not acquired_lock: + # we're exiting due to an exception while acquiring the lot + task_cr.close() + # Got the lock on the job row, now spawn a thread to execute it in the transaction with the lock + task_thread = threading.Thread(target=self._run_job, name=job['name'], args=(task_cr, job, now)) + # force non-daemon task threads (the runner thread must be daemon, and this property is inherited by default) + task_thread.setDaemon(False) + openerp.cron.take_thread_slot() + task_thread.start() + self._logger.debug('Cron execution thread for job `%s` spawned', job['name']) - cr.execute('select min(nextcall) as min_next_call from ir_cron where numbercall<>0 and active') - next_call = cr.dictfetchone()['min_next_call'] - if next_call: - next_call = time.mktime(time.strptime(next_call, '%Y-%m-%d %H:%M:%S')) + # Find next earliest job ignoring currently processed jobs (by this and other cron threads) + find_next_time_query = """SELECT min(nextcall) AS min_next_call + FROM ir_cron WHERE numbercall != 0 AND active""" + if jobs: + cr.execute(find_next_time_query + " AND id NOT IN %s", (tuple(jobs.keys()),)) else: - next_call = int(time.time()) + 3600 # if do not find active cron job from database, it will run again after 1 day + cr.execute(find_next_time_query) + next_call = cr.dictfetchone()['min_next_call'] - if not check: - self.setAlarm(self._poolJobs, next_call, db_name, db_name) + if next_call: + next_call = time.mktime(time.strptime(next_call, DEFAULT_SERVER_DATETIME_FORMAT)) + else: + # no matching cron job found in database, re-schedule arbitrarily in 1 day, + # this delay will likely be modified when running jobs complete their tasks + next_call = time.time() + (24*3600) + + openerp.cron.schedule_wakeup(next_call, db_name) except Exception, ex: self._logger.warning('Exception in cron:', exc_info=True) @@ -156,12 +266,8 @@ class ir_cron(osv.osv, netsvc.Agent): cr.commit() cr.close() - def restart(self, dbname): - self.cancel(dbname) - # Reschedule cron processing job asap, but not in the current thread - self.setAlarm(self._poolJobs, time.time(), dbname, dbname) - def update_running_cron(self, cr): + """ Schedule as soon as possible a wake-up for this database. """ # Verify whether the server is already started and thus whether we need to commit # immediately our changes and restart the cron agent in order to apply the change # immediately. The commit() is needed because as soon as the cron is (re)started it @@ -171,23 +277,37 @@ class ir_cron(osv.osv, netsvc.Agent): # when the server is only starting or loading modules (hence the test on pool._init). if not self.pool._init: cr.commit() - self.restart(cr.dbname) + openerp.cron.schedule_wakeup(WAKE_UP_NOW, self.pool.db.dbname) + + def _try_lock(self, cr, uid, ids, context=None): + """Try to grab a dummy exclusive write-lock to the rows with the given ids, + to make sure a following write() or unlink() will not block due + to a process currently executing those cron tasks""" + try: + cr.execute("""SELECT id FROM "%s" WHERE id IN %%s FOR UPDATE NOWAIT""" % self._table, + (tuple(ids),), log_exceptions=False) + except psycopg2.OperationalError: + cr.rollback() # early rollback to allow translations to work for the user feedback + raise osv.except_osv(_("Record cannot be modified right now"), + _("This cron task is currently being executed and may not be modified, " + "please try again in a few minutes")) def create(self, cr, uid, vals, context=None): res = super(ir_cron, self).create(cr, uid, vals, context=context) self.update_running_cron(cr) return res - def write(self, cr, user, ids, vals, context=None): - res = super(ir_cron, self).write(cr, user, ids, vals, context=context) + def write(self, cr, uid, ids, vals, context=None): + self._try_lock(cr, uid, ids, context) + res = super(ir_cron, self).write(cr, uid, ids, vals, context=context) self.update_running_cron(cr) return res def unlink(self, cr, uid, ids, context=None): + self._try_lock(cr, uid, ids, context) res = super(ir_cron, self).unlink(cr, uid, ids, context=context) self.update_running_cron(cr) return res ir_cron() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: - diff --git a/openerp/addons/base/ir/ir_mail_server.py b/openerp/addons/base/ir/ir_mail_server.py index 0701412043c..96fa9f52a88 100644 --- a/openerp/addons/base/ir/ir_mail_server.py +++ b/openerp/addons/base/ir/ir_mail_server.py @@ -189,7 +189,7 @@ class ir_mail_server(osv.osv): password=smtp_server.smtp_pass, encryption=smtp_server.smtp_encryption, smtp_debug=smtp_server.smtp_debug) except Exception, e: - raise osv.except_osv(_("Connection test failed!"), _("Here is what we got instead:\n %s") % e) + raise osv.except_osv(_("Connection test failed!"), _("Here is what we got instead:\n %s") % tools.ustr(e)) finally: try: if smtp: smtp.quit() diff --git a/openerp/addons/base/ir/ir_model.py b/openerp/addons/base/ir/ir_model.py index 1ae54af0cb9..395bf3e8d60 100644 --- a/openerp/addons/base/ir/ir_model.py +++ b/openerp/addons/base/ir/ir_model.py @@ -56,14 +56,14 @@ def _in_modules(self, cr, uid, ids, field_name, arg, context=None): class ir_model(osv.osv): _name = 'ir.model' - _description = "Objects" + _description = "Models" _order = 'model' def _is_osv_memory(self, cr, uid, ids, field_name, arg, context=None): models = self.browse(cr, uid, ids, context=context) res = dict.fromkeys(ids) for model in models: - res[model.id] = isinstance(self.pool.get(model.model), osv.osv_memory) + res[model.id] = self.pool.get(model.model).is_transient() return res def _search_osv_memory(self, cr, uid, model, name, domain, context=None): @@ -85,8 +85,8 @@ class ir_model(osv.osv): return res _columns = { - 'name': fields.char('Object Name', size=64, translate=True, required=True), - 'model': fields.char('Object', size=64, required=True, select=1), + 'name': fields.char('Model Description', size=64, translate=True, required=True), + 'model': fields.char('Model', size=64, required=True, select=1), 'info': fields.text('Information'), 'field_id': fields.one2many('ir.model.fields', 'model_id', 'Fields', required=True), 'state': fields.selection([('manual','Custom Object'),('base','Base Object')],'Type',readonly=True), @@ -97,12 +97,12 @@ class ir_model(osv.osv): 'modules': fields.function(_in_modules, method=True, type='char', size=128, string='In modules', help='List of modules in which the object is defined or inherited'), 'view_ids': fields.function(_view_ids, method=True, type='one2many', obj='ir.ui.view', string='Views'), } - + _defaults = { 'model': lambda *a: 'x_', 'state': lambda self,cr,uid,ctx=None: (ctx and ctx.get('manual',False)) and 'manual' or 'base', } - + def _check_model_name(self, cr, uid, ids, context=None): for model in self.browse(cr, uid, ids, context=context): if model.state=='manual': @@ -114,9 +114,13 @@ class ir_model(osv.osv): def _model_name_msg(self, cr, uid, ids, context=None): return _('The Object name must start with x_ and not contain any special character !') + _constraints = [ (_check_model_name, _model_name_msg, ['model']), ] + _sql_constraints = [ + ('obj_name_uniq', 'unique (model)', 'Each model must be unique!'), + ] # overridden to allow searching both on model name (model field) # and model description (name field) @@ -161,7 +165,7 @@ class ir_model(osv.osv): pass x_custom_model._name = model x_custom_model._module = False - a = x_custom_model.createInstance(self.pool, cr) + a = x_custom_model.create_instance(self.pool, cr) if (not a._columns) or ('x_name' in a._columns.keys()): x_name = 'x_name' else: @@ -477,14 +481,12 @@ class ir_model_access(osv.osv): if isinstance(model, browse_record): assert model._table_name == 'ir.model', 'Invalid model object' - model_name = model.name + model_name = model.model else: model_name = model - # osv_memory objects can be read by everyone, as they only return - # results that belong to the current user (except for superuser) - model_obj = self.pool.get(model_name) - if isinstance(model_obj, osv.osv_memory): + # TransientModel records have no access rights, only an implicit access rule + if self.pool.get(model_name).is_transient(): return True # We check if a specific rule exists @@ -519,7 +521,7 @@ class ir_model_access(osv.osv): } raise except_orm(_('AccessError'), msgs[mode] % (model_name, groups) ) - return r + return r or False __cache_clearing_methods = [] @@ -616,7 +618,7 @@ class ir_model_data(osv.osv): """Returns the id of the ir.model.data record corresponding to a given module and xml_id (cached) or raise a ValueError if not found""" ids = self.search(cr, uid, [('module','=',module), ('name','=', xml_id)]) if not ids: - raise ValueError('No references to %s.%s' % (module, xml_id)) + raise ValueError('No such external ID currently defined in the system: %s.%s' % (module, xml_id)) # the sql constraints ensure us we have only one result return ids[0] @@ -626,7 +628,7 @@ class ir_model_data(osv.osv): data_id = self._get_id(cr, uid, module, xml_id) res = self.read(cr, uid, data_id, ['model', 'res_id']) if not res['res_id']: - raise ValueError('No references to %s.%s' % (module, xml_id)) + raise ValueError('No such external ID currently defined in the system: %s.%s' % (module, xml_id)) return (res['model'], res['res_id']) def get_object(self, cr, uid, module, xml_id, context=None): diff --git a/openerp/addons/base/ir/ir_rule.py b/openerp/addons/base/ir/ir_rule.py index 734d00eb9a2..33f926e55c2 100644 --- a/openerp/addons/base/ir/ir_rule.py +++ b/openerp/addons/base/ir/ir_rule.py @@ -26,8 +26,7 @@ from functools import partial import tools from tools.safe_eval import safe_eval as eval from tools.misc import unquote as unquote - -SUPERUSER_UID = 1 +from openerp import SUPERUSER_ID class ir_rule(osv.osv): _name = 'ir.rule' @@ -68,7 +67,7 @@ class ir_rule(osv.osv): return res def _check_model_obj(self, cr, uid, ids, context=None): - return not any(isinstance(self.pool.get(rule.model_id.model), osv.osv_memory) for rule in self.browse(cr, uid, ids, context)) + return not any(self.pool.get(rule.model_id.model).is_transient() for rule in self.browse(cr, uid, ids, context)) _columns = { 'name': fields.char('Name', size=128, select=1), @@ -104,7 +103,7 @@ class ir_rule(osv.osv): if mode not in self._MODES: raise ValueError('Invalid mode: %r' % (mode,)) - if uid == SUPERUSER_UID: + if uid == SUPERUSER_ID: return None cr.execute("""SELECT r.id FROM ir_rule r @@ -117,10 +116,10 @@ class ir_rule(osv.osv): rule_ids = [x[0] for x in cr.fetchall()] if rule_ids: # browse user as super-admin root to avoid access errors! - user = self.pool.get('res.users').browse(cr, SUPERUSER_UID, uid) + user = self.pool.get('res.users').browse(cr, SUPERUSER_ID, uid) global_domains = [] # list of domains group_domains = {} # map: group -> list of domains - for rule in self.browse(cr, SUPERUSER_UID, rule_ids): + for rule in self.browse(cr, SUPERUSER_ID, rule_ids): # read 'domain' as UID to have the correct eval context for the rule. rule_domain = self.read(cr, uid, rule.id, ['domain'])['domain'] dom = expression.normalize(rule_domain) diff --git a/openerp/addons/base/ir/ir_ui_view.py b/openerp/addons/base/ir/ir_ui_view.py index 90990834c9b..c44ff716519 100644 --- a/openerp/addons/base/ir/ir_ui_view.py +++ b/openerp/addons/base/ir/ir_ui_view.py @@ -96,6 +96,19 @@ class view(osv.osv): if not cr.fetchone(): cr.execute('CREATE INDEX ir_ui_view_model_type_inherit_id ON ir_ui_view (model, type, inherit_id)') + def get_inheriting_views_arch(self, cr, uid, view_id, model, context=None): + """Retrieves the architecture of views that inherit from the given view. + + :param int view_id: id of the view whose inheriting views should be retrieved + :param str model: model identifier of the view's related model (for double-checking) + :rtype: list of tuples + :return: [(view_arch,view_id), ...] + """ + cr.execute("""SELECT arch, id FROM ir_ui_view WHERE inherit_id=%s AND model=%s + ORDER BY priority""", + (view_id, model)) + return cr.fetchall() + def write(self, cr, uid, ids, vals, context={}): if not isinstance(ids, (list, tuple)): ids = [ids] @@ -159,10 +172,10 @@ class view(osv.osv): label_string = "" if label: for lbl in eval(label): - if t.has_key(str(lbl)) and str(t[lbl])=='False': + if t.has_key(tools.ustr(lbl)) and tools.ustr(t[lbl])=='False': label_string = label_string + ' ' else: - label_string = label_string + " " + t[lbl] + label_string = label_string + " " + tools.ustr(t[lbl]) labels[str(t['id'])] = (a['id'],label_string) g = graph(nodes, transitions, no_ancester) g.process(start) diff --git a/openerp/addons/base/ir/osv_memory_autovacuum.py b/openerp/addons/base/ir/osv_memory_autovacuum.py index b2ab938d740..975fcd0a403 100644 --- a/openerp/addons/base/ir/osv_memory_autovacuum.py +++ b/openerp/addons/base/ir/osv_memory_autovacuum.py @@ -19,18 +19,15 @@ # ############################################################################## -from osv import osv -from osv.orm import orm_memory +import openerp -class osv_memory_autovacuum(osv.osv_memory): +class osv_memory_autovacuum(openerp.osv.osv.osv_memory): + """ Expose the osv_memory.vacuum() method to the cron jobs mechanism. """ _name = 'osv_memory.autovacuum' def power_on(self, cr, uid, context=None): - for model in self.pool.obj_list(): - obj = self.pool.get(model) - if isinstance(obj, orm_memory): - obj.vaccum(cr, uid) + for model in self.pool.models.values(): + if model.is_transient(): + model._transient_vacuum(cr, uid) return True -osv_memory_autovacuum() - diff --git a/openerp/addons/base/ir/wizard/__init__.py b/openerp/addons/base/ir/wizard/__init__.py index 99c6cdcd0de..3f5495524f5 100644 --- a/openerp/addons/base/ir/wizard/__init__.py +++ b/openerp/addons/base/ir/wizard/__init__.py @@ -20,6 +20,5 @@ ############################################################################## import wizard_menu import wizard_screen -import create_action # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerp/addons/base/ir/wizard/create_action.py b/openerp/addons/base/ir/wizard/create_action.py deleted file mode 100644 index 335f7a5ce04..00000000000 --- a/openerp/addons/base/ir/wizard/create_action.py +++ /dev/null @@ -1,77 +0,0 @@ -# -*- coding: utf-8 -*- - ############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-2009 Tiny SPRL (). -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## - -import wizard -import pooler -import time - -action_type = ''' -
- -''' - -action_type_fields = { - 'type': {'string':"Select Action Type",'type':'selection','required':True ,'selection':[('ir.actions.report.xml','Open Report')]}, -} - -report_action = ''' -
- -''' - -report_action_fields = { - 'report': {'string':"Select Report",'type':'many2one','relation':'ir.actions.report.xml', 'required':True}, -} - -class create_action(wizard.interface): - - def _create_report_action(self, cr, uid, data, context={}): - pool = pooler.get_pool(cr.dbname) - - reports = pool.get('ir.actions.report.xml') - form = data['form'] - - rpt = reports.browse(cr, uid, form['report']) - - action = """action = {"type": "ir.actions.report.xml","model":"%s","report_name": "%s","ids": context["active_ids"]}""" % (rpt.model, rpt.report_name) - - obj = pool.get('ir.actions.server') - obj.write(cr, uid, data['ids'], {'code':action}) - - return {} - - states = { - 'init': { - 'actions': [], - 'result': {'type':'form', 'arch':action_type,'fields':action_type_fields, 'state':[('step_1','Next'),('end','Close')]} - }, - 'step_1': { - 'actions': [], - 'result': {'type':'form', 'arch':report_action,'fields':report_action_fields, 'state':[('create','Create'),('end','Close')]} - }, - 'create': { - 'actions': [_create_report_action], - 'result': {'type':'state', 'state':'end'} - }, - } -create_action('server.action.create') - - diff --git a/openerp/addons/base/ir/wizard/wizard_menu_view.xml b/openerp/addons/base/ir/wizard/wizard_menu_view.xml index 4d3e7e7a26e..d99138d00e6 100644 --- a/openerp/addons/base/ir/wizard/wizard_menu_view.xml +++ b/openerp/addons/base/ir/wizard/wizard_menu_view.xml @@ -21,12 +21,5 @@
- diff --git a/openerp/addons/base/module/module.py b/openerp/addons/base/module/module.py index 034829b82b5..a35e4b5d1ce 100644 --- a/openerp/addons/base/module/module.py +++ b/openerp/addons/base/module/module.py @@ -107,48 +107,59 @@ class module(osv.osv): view_obj = self.pool.get('ir.ui.view') report_obj = self.pool.get('ir.actions.report.xml') menu_obj = self.pool.get('ir.ui.menu') - mlist = self.browse(cr, uid, ids, context=context) - mnames = {} - for m in mlist: - # skip uninstalled modules below, - # no data to find anyway - if m.state in ('installed', 'to upgrade', 'to remove'): - mnames[m.name] = m.id - res[m.id] = { - 'menus_by_module':[], - 'reports_by_module':[], + + dmodels = [] + if field_name is None or 'views_by_module' in field_name: + dmodels.append('ir.ui.view') + if field_name is None or 'reports_by_module' in field_name: + dmodels.append('ir.actions.report.xml') + if field_name is None or 'menus_by_module' in field_name: + dmodels.append('ir.ui.menu') + assert dmodels, "no models for %s" % field_name + + for module_rec in self.browse(cr, uid, ids, context=context): + res[module_rec.id] = { + 'menus_by_module': [], + 'reports_by_module': [], 'views_by_module': [] } - if not mnames: - return res + # Skip uninstalled modules below, no data to find anyway. + if module_rec.state not in ('installed', 'to upgrade', 'to remove'): + continue - view_id = model_data_obj.search(cr,uid,[('module','in', mnames.keys()), - ('model','in',('ir.ui.view','ir.actions.report.xml','ir.ui.menu'))]) - for data_id in model_data_obj.browse(cr,uid,view_id,context): - # We use try except, because views or menus may not exist + # then, search and group ir.model.data records + imd_models = dict( [(m,[]) for m in dmodels]) + imd_ids = model_data_obj.search(cr,uid,[('module','=', module_rec.name), + ('model','in',tuple(dmodels))]) + + for imd_res in model_data_obj.read(cr, uid, imd_ids, ['model', 'res_id'], context=context): + imd_models[imd_res['model']].append(imd_res['res_id']) + + # For each one of the models, get the names of these ids. + # We use try except, because views or menus may not exist. try: - key = data_id.model - res_mod_dic = res[mnames[data_id.module]] - if key=='ir.ui.view': - v = view_obj.browse(cr,uid,data_id.res_id) + res_mod_dic = res[module_rec.id] + for v in view_obj.browse(cr, uid, imd_models.get('ir.ui.view', []), context=context): aa = v.inherit_id and '* INHERIT ' or '' res_mod_dic['views_by_module'].append(aa + v.name + '('+v.type+')') - elif key=='ir.actions.report.xml': - res_mod_dic['reports_by_module'].append(report_obj.browse(cr,uid,data_id.res_id).name) - elif key=='ir.ui.menu': - res_mod_dic['menus_by_module'].append(menu_obj.browse(cr,uid,data_id.res_id).complete_name) + + for rx in report_obj.browse(cr, uid, imd_models.get('ir.actions.report.xml', []), context=context): + res_mod_dic['reports_by_module'].append(rx.name) + + for um in menu_obj.browse(cr, uid, imd_models.get('ir.ui.menu', []), context=context): + res_mod_dic['menus_by_module'].append(um.complete_name) except KeyError, e: self.__logger.warning( - 'Data not found for reference %s[%s:%s.%s]', data_id.model, - data_id.res_id, data_id.model, data_id.name, exc_info=True) - pass + 'Data not found for items of %s', module_rec.name) + except AttributeError, e: + self.__logger.warning( + 'Data not found for items of %s %s', module_rec.name, str(e)) except Exception, e: - self.__logger.warning('Unknown error while browsing %s[%s]', - data_id.model, data_id.res_id, exc_info=True) - pass + self.__logger.warning('Unknown error while fetching data of %s', + module_rec.name, exc_info=True) for key, value in res.iteritems(): - for k, v in res[key].iteritems() : + for k, v in res[key].iteritems(): res[key][k] = "\n".join(sorted(v)) return res @@ -437,12 +448,11 @@ class module(osv.osv): res.append(mod.url) if not download: continue - zipfile = urllib.urlopen(mod.url).read() + zip_content = urllib.urlopen(mod.url).read() fname = addons.get_module_path(str(mod.name)+'.zip', downloaded=True) try: - fp = file(fname, 'wb') - fp.write(zipfile) - fp.close() + with open(fname, 'wb') as fp: + fp.write(zip_content) except Exception: self.__logger.exception('Error when trying to create module ' 'file %s', fname) diff --git a/openerp/addons/base/module/wizard/base_import_language.py b/openerp/addons/base/module/wizard/base_import_language.py index d73cd0864a6..fdb9a177d8b 100644 --- a/openerp/addons/base/module/wizard/base_import_language.py +++ b/openerp/addons/base/module/wizard/base_import_language.py @@ -35,9 +35,12 @@ class base_language_import(osv.osv_memory): 'name': fields.char('Language Name',size=64 , required=True), 'code': fields.char('Code (eg:en__US)',size=5 , required=True), 'data': fields.binary('File', required=True), + 'overwrite': fields.boolean('Overwrite Existing Terms', + help="If you enable this option, existing translations (including custom ones) " + "will be overwritten and replaced by those in this file"), } - def import_lang(self, cr, uid, ids, context): + def import_lang(self, cr, uid, ids, context=None): """ Import Language @param cr: the current row, from the database cursor. @@ -45,8 +48,11 @@ class base_language_import(osv.osv_memory): @param ids: the ID or list of IDs @param context: A standard dictionary """ - + if context is None: + context = {} import_data = self.browse(cr, uid, ids)[0] + if import_data.overwrite: + context.update(overwrite=True) fileobj = TemporaryFile('w+') fileobj.write(base64.decodestring(import_data.data)) @@ -56,7 +62,7 @@ class base_language_import(osv.osv_memory): fileformat = first_line.endswith("type,name,res_id,src,value") and 'csv' or 'po' fileobj.seek(0) - tools.trans_load_data(cr, fileobj, fileformat, import_data.code, lang_name=import_data.name) + tools.trans_load_data(cr, fileobj, fileformat, import_data.code, lang_name=import_data.name, context=context) tools.trans_update_res_ids(cr) fileobj.close() return {} diff --git a/openerp/addons/base/module/wizard/base_import_language_view.xml b/openerp/addons/base/module/wizard/base_import_language_view.xml index d313afc4080..4a1d7e5b758 100644 --- a/openerp/addons/base/module/wizard/base_import_language_view.xml +++ b/openerp/addons/base/module/wizard/base_import_language_view.xml @@ -27,6 +27,7 @@ + diff --git a/openerp/addons/base/module/wizard/base_module_import.py b/openerp/addons/base/module/wizard/base_module_import.py index 05c3b18198d..3ef9132af0e 100644 --- a/openerp/addons/base/module/wizard/base_module_import.py +++ b/openerp/addons/base/module/wizard/base_module_import.py @@ -28,6 +28,8 @@ import base64 from tools.translate import _ from osv import osv, fields +ADDONS_PATH = tools.config['addons_path'].split(",")[-1] + class base_module_import(osv.osv_memory): """ Import Module """ @@ -37,7 +39,8 @@ class base_module_import(osv.osv_memory): _columns = { 'module_file': fields.binary('Module .ZIP file', required=True), - 'state':fields.selection([('init','init'),('done','done')], 'state', readonly=True), + 'state':fields.selection([('init','init'),('done','done')], + 'state', readonly=True), 'module_name': fields.char('Module Name', size=128), } @@ -48,26 +51,30 @@ class base_module_import(osv.osv_memory): def importzip(self, cr, uid, ids, context): (data,) = self.browse(cr, uid, ids , context=context) module_data = data.module_file - - val = base64.decodestring(module_data) + zip_data = base64.decodestring(module_data) fp = StringIO() - fp.write(val) - fdata = zipfile.ZipFile(fp, 'r') - fname = fdata.namelist()[0] - module_name = os.path.split(fname)[0] - - ad = tools.config['addons_path'].split(",")[-1] - - fname = os.path.join(ad, module_name+'.zip') + fp.write(zip_data) try: - fp = file(fname, 'wb') - fp.write(val) - fp.close() - except IOError: - raise osv.except_osv(_('Error !'), _('Can not create the module file: %s !') % (fname,) ) + file_data = zipfile.ZipFile(fp, 'r') + except zipfile.BadZipfile: + raise osv.except_osv(_('Error !'), _('File is not a zip file!')) + init_file_name = sorted(file_data.namelist())[0] + module_name = os.path.split(init_file_name)[0] - self.pool.get('ir.module.module').update_list(cr, uid, {'module_name': module_name,}) - self.write(cr, uid, ids, {'state':'done', 'module_name': module_name}, context) + file_path = os.path.join(ADDONS_PATH, '%s.zip' % module_name) + try: + zip_file = open(file_path, 'wb') + except IOError: + raise osv.except_osv(_('Error !'), + _('Can not create the module file: %s !') % \ + (file_path,) ) + zip_file.write(zip_data) + zip_file.close() + + self.pool.get('ir.module.module').update_list(cr, uid, + {'module_name': module_name,}) + self.write(cr, uid, ids, {'state':'done', 'module_name': module_name}, + context) return False def action_module_open(self, cr, uid, ids, context): @@ -84,4 +91,4 @@ class base_module_import(osv.osv_memory): base_module_import() -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: \ No newline at end of file +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerp/addons/base/module/wizard/base_module_import_view.xml b/openerp/addons/base/module/wizard/base_module_import_view.xml index 8e43789b057..0ca3e14ea96 100644 --- a/openerp/addons/base/module/wizard/base_module_import_view.xml +++ b/openerp/addons/base/module/wizard/base_module_import_view.xml @@ -12,9 +12,10 @@ - diff --git a/openerp/addons/base/res/ir_property_view.xml b/openerp/addons/base/res/ir_property_view.xml index af836a3c92e..67b3357a4df 100644 --- a/openerp/addons/base/res/ir_property_view.xml +++ b/openerp/addons/base/res/ir_property_view.xml @@ -13,6 +13,7 @@ help="Parameters that are used by all resources." domain="[('res_id','=',False)]"/> + diff --git a/openerp/addons/base/res/res_company.py b/openerp/addons/base/res/res_company.py index 3ad0cfcfb55..51d796a3a1e 100644 --- a/openerp/addons/base/res/res_company.py +++ b/openerp/addons/base/res/res_company.py @@ -143,6 +143,9 @@ class res_company(osv.osv): 'vat': fields.related('partner_id', 'vat', string="Tax ID", type="char", size=32), 'company_registry': fields.char('Company Registry', size=64), } + _sql_constraints = [ + ('name_uniq', 'unique (name)', 'The company name must be unique !') + ] def _search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False, access_rights_uid=None): @@ -242,9 +245,7 @@ class res_company(osv.osv): return False def _get_logo(self, cr, uid, ids): - return open(os.path.join( - tools.config['root_path'], '..', 'pixmaps', 'your_logo.png'), - 'rb') .read().encode('base64') + return open(os.path.join( tools.config['root_path'], 'addons', 'base', 'res', 'res_company_logo.png'), 'rb') .read().encode('base64') _header = """
diff --git a/pixmaps/your_logo.png b/openerp/addons/base/res/res_company_logo.png similarity index 100% rename from pixmaps/your_logo.png rename to openerp/addons/base/res/res_company_logo.png diff --git a/openerp/addons/base/res/res_currency.py b/openerp/addons/base/res/res_currency.py index 3b7e427a923..01d8b745e6f 100644 --- a/openerp/addons/base/res/res_currency.py +++ b/openerp/addons/base/res/res_currency.py @@ -62,17 +62,36 @@ class res_currency(osv.osv): 'active': fields.boolean('Active'), 'company_id':fields.many2one('res.company', 'Company'), 'date': fields.date('Date'), - 'base': fields.boolean('Base') - + 'base': fields.boolean('Base'), + 'position': fields.selection([('after','After Amount'),('before','Before Amount')], 'Symbol position', help="Determines where the currency symbol should be placed after or before the amount.") } _defaults = { 'active': lambda *a: 1, - 'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'res.currency', context=c) + 'position' : 'after', } + _sql_constraints = [ + # this constraint does not cover all cases due to SQL NULL handling for company_id, + # so it is complemented with a unique index (see below). The constraint and index + # share the same prefix so that IntegrityError triggered by the index will be caught + # and reported to the user with the constraint's error message. + ('unique_name_company_id', 'unique (name, company_id)', 'The currency code must be unique per company!'), + ] _order = "name" + def init(self, cr): + # CONSTRAINT/UNIQUE INDEX on (name,company_id) + # /!\ The unique constraint 'unique_name_company_id' is not sufficient, because SQL92 + # only support field names in constraint definitions, and we need a function here: + # we need to special-case company_id to treat all NULL company_id as equal, otherwise + # we would allow duplicate "global" currencies (all having company_id == NULL) + cr.execute("""SELECT indexname FROM pg_indexes WHERE indexname = 'res_currency_unique_name_company_id_idx'""") + if not cr.fetchone(): + cr.execute("""CREATE UNIQUE INDEX res_currency_unique_name_company_id_idx + ON res_currency + (name, (COALESCE(company_id,-1)))""") + def read(self, cr, user, ids, fields=None, context=None, load='_classic_read'): - res = super(osv.osv, self).read(cr, user, ids, fields, context, load) + res = super(res_currency, self).read(cr, user, ids, fields, context, load) currency_rate_obj = self.pool.get('res.currency.rate') for r in res: if r.__contains__('rate_ids'): @@ -150,7 +169,7 @@ res_currency() class res_currency_rate_type(osv.osv): _name = "res.currency.rate.type" - _description = "Used to define the type of Currency Rates" + _description = "Currency Rate Type" _columns = { 'name': fields.char('Name', size=64, required=True, translate=True), } diff --git a/openerp/addons/base/res/res_currency_view.xml b/openerp/addons/base/res/res_currency_view.xml index 8d747c882b1..7dab4c051f4 100644 --- a/openerp/addons/base/res/res_currency_view.xml +++ b/openerp/addons/base/res/res_currency_view.xml @@ -2,6 +2,18 @@ + + res.currency.search + res.currency + search + + + + + + + + res.currency.tree res.currency @@ -9,12 +21,13 @@ - + + @@ -25,23 +38,30 @@ form
- - + + - - + - - - - - + + + + + + - - - - + + + + + + + + + + + @@ -62,6 +82,7 @@ res.currency form tree,form + diff --git a/openerp/addons/base/res/res_partner_demo.xml b/openerp/addons/base/res/res_partner_demo.xml index 8f2f661234d..c6616cd20bb 100644 --- a/openerp/addons/base/res/res_partner_demo.xml +++ b/openerp/addons/base/res/res_partner_demo.xml @@ -90,36 +90,44 @@ ASUStek - 1 + + www.asustek.com Agrolait - + + + www.agrolait.com Camptocamp 1 + + www.camptocamp.com - http://www.syleam.fr + www.syleam.fr Syleam + Thymbra + + www.thymbra.com/ Axelor @@ -127,41 +135,54 @@ 1 + + www.axelor.com/ Tiny AT Work + + www.tinyatwork.com/ Bank Wealthy and sons + + www.wealthyandsons.com/ China Export + + www.chinaexport.com/ Distrib PC 1 + + www.distribpc.com/ Ecole de Commerce de Liege + + www.eci-liege.info// Elec Import 1 + @@ -171,6 +192,7 @@ 1 + @@ -192,11 +214,11 @@ - http://balmerinc.com + www.balmerinc.com BalmerInc S.A. or - + @@ -207,6 +229,7 @@ + Leclerc @@ -224,6 +247,7 @@ + Magazin BML 1 @@ -240,6 +264,8 @@ + + http://www.ulg.ac.be/ - ['|','|',('company_id.child_ids','child_of',[user.company_id.id]),('company_id','child_of',[user.company_id.id]),('company_id','=',False)] - + - - Multi_company_default company - - - [('company_id','child_of',[user.company_id.id])] - + + res.widget.user rule + + + ['|', ('user_id','=',user.id),('user_id','=',False)] + + + + res.partner company + + + + ['|','|',('company_id.child_ids','child_of',[user.company_id.id]),('company_id','child_of',[user.company_id.id]),('company_id','=',False)] + + + + Multi_company_default company + + + [('company_id','child_of',[user.company_id.id])] + diff --git a/openerp/addons/base/security/ir.model.access.csv b/openerp/addons/base/security/ir.model.access.csv index aa46c1891e7..659938a73a3 100644 --- a/openerp/addons/base/security/ir.model.access.csv +++ b/openerp/addons/base/security/ir.model.access.csv @@ -48,6 +48,7 @@ "access_res_country_state_group_user","res_country_state group_user","model_res_country_state","group_partner_manager",1,1,1,1 "access_res_currency_group_all","res_currency group_all","model_res_currency",,1,0,0,0 "access_res_currency_rate_group_all","res_currency_rate group_all","model_res_currency_rate",,1,0,0,0 +"access_res_currency_rate_type_group_all","res_currency_rate_type group_all","model_res_currency_rate_type",,1,0,0,0 "access_res_currency_group_system","res_currency group_system","model_res_currency","group_system",1,1,1,1 "access_res_currency_rate_group_system","res_currency_rate group_system","model_res_currency_rate","group_system",1,1,1,1 "access_res_groups_group_erp_manager","res_groups group_erp_manager","model_res_groups","group_erp_manager",1,1,1,1 @@ -125,3 +126,4 @@ "access_ir_config_parameter","ir_config_parameter","model_ir_config_parameter",,1,0,0,0 "access_ir_mail_server_all","ir_mail_server","model_ir_mail_server",,1,0,0,0 "access_ir_actions_todo_category","ir_actions_todo_category","model_ir_actions_todo_category","group_system",1,1,1,1 +"access_ir_actions_client","ir_actions_client all","model_ir_actions_client",,1,0,0,0 diff --git a/openerp/addons/base/test/__init__.py b/openerp/addons/base/test/__init__.py new file mode 100644 index 00000000000..c0cc8f7cb78 --- /dev/null +++ b/openerp/addons/base/test/__init__.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2011-TODAY OpenERP S.A. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +# Useful for manual testing of cron jobs scheduling. +# This must be (un)commented with the corresponding yml file +# in ../__openerp__.py. +# import test_ir_cron + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerp/addons/base/test/base_test.yml b/openerp/addons/base/test/base_test.yml index 5a17ca108c3..6ea578a8659 100644 --- a/openerp/addons/base/test/base_test.yml +++ b/openerp/addons/base/test/base_test.yml @@ -144,45 +144,3 @@ !python {model: res.partner.category}: | self.pool._init = True -- - "OSV Memory: Verify that osv_memory properly handles large data allocation" -- - 1. No "count-based" auto-vaccuum when max_count is disabled -- - !python {model: base.language.export}: | - # setup special limits for the test, these will be reset at next pool reload anyway - self._max_count = None - num_recs = 250 - for i in xrange(num_recs): - self.create(cr, uid, {'format':'po'}) - assert (len(self.datas) >= num_recs), "OSV Memory must not auto-vaccum records from the current transaction if max_count is not set" -- - 2. Auto-vaccuum should be enabled when max_count is set -- - !python {model: base.language.export}: | - # setup special limits for the test, these will be reset at next pool reload anyway - self._max_count = 100 - num_recs = 219 - for i in xrange(num_recs): - self.create(cr, uid, {'name': i, 'format':'po'}) - assert (self._max_count <= len(self.datas) < self._max_count + self._check_time), "OSV Memory must auto-expire records when max_count is reached" - for k,v in self.datas.iteritems(): - assert (int(v['name']) >= (num_recs - (self._max_count + self._check_time))), "OSV Memory must auto-expire records based on age" -- - 3. Auto-vaccuum should be based on age only when max_count is not set -- - !python {model: base.language.export}: | - # setup special limits for the test, these will be reset at next pool reload anyway - self._max_count = None - self._max_hours = 0.01 #36 seconds - num_recs = 200 - for i in xrange(num_recs): - self.create(cr, uid, {'format':'po'}) - assert (len(self.datas) >= num_recs), "OSV Memory must not auto-expire records from the current transaction" - - # expire all records - for k,v in self.datas.iteritems(): - v['internal.date_access'] = 0 - self.vaccum(cr, 1, force=True) - - assert (len(self.datas) == 0), "OSV Memory must expire old records after vaccuum" diff --git a/openerp/addons/base/test/test_ir_cron.py b/openerp/addons/base/test/test_ir_cron.py new file mode 100644 index 00000000000..6ef79ac3a78 --- /dev/null +++ b/openerp/addons/base/test/test_ir_cron.py @@ -0,0 +1,116 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2011-TODAY OpenERP S.A. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +import time +from datetime import datetime +from dateutil.relativedelta import relativedelta + +import openerp + +JOB = { + 'function': u'_0_seconds', + 'interval_type': u'minutes', + 'user_id': 1, + 'name': u'test', + 'args': False, + 'numbercall': 1, + 'nextcall': datetime.now().strftime('%Y-%m-%d %H:%M:%S'), + 'priority': 5, + 'doall': True, + 'active': True, + 'interval_number': 1, + 'model': u'ir.cron' +} + +class test_ir_cron(openerp.osv.osv.osv): + """ Add a few handy methods to test cron jobs scheduling. """ + _inherit = "ir.cron" + + def _0_seconds(a, b, c): + print ">>> _0_seconds" + + def _20_seconds(self, cr, uid): + print ">>> in _20_seconds" + time.sleep(20) + print ">>> out _20_seconds" + + def _80_seconds(self, cr, uid): + print ">>> in _80_seconds" + time.sleep(80) + print ">>> out _80_seconds" + + def test_0(self, cr, uid): + now = datetime.now() + t1 = (now + relativedelta(minutes=1)).strftime('%Y-%m-%d %H:%M:%S') + t2 = (now + relativedelta(minutes=1, seconds=5)).strftime('%Y-%m-%d %H:%M:%S') + t3 = (now + relativedelta(minutes=1, seconds=10)).strftime('%Y-%m-%d %H:%M:%S') + self.create(cr, uid, dict(JOB, name='test_0 _20_seconds A', function='_20_seconds', nextcall=t1)) + self.create(cr, uid, dict(JOB, name='test_0 _20_seconds B', function='_20_seconds', nextcall=t2)) + self.create(cr, uid, dict(JOB, name='test_0 _20_seconds C', function='_20_seconds', nextcall=t3)) + + def test_1(self, cr, uid): + now = datetime.now() + t1 = (now + relativedelta(minutes=1)).strftime('%Y-%m-%d %H:%M:%S') + self.create(cr, uid, dict(JOB, name='test_1 _20_seconds * 3', function='_20_seconds', nextcall=t1, numbercall=3)) + + def test_2(self, cr, uid): + now = datetime.now() + t1 = (now + relativedelta(minutes=1)).strftime('%Y-%m-%d %H:%M:%S') + self.create(cr, uid, dict(JOB, name='test_2 _80_seconds * 2', function='_80_seconds', nextcall=t1, numbercall=2)) + + def test_3(self, cr, uid): + now = datetime.now() + t1 = (now + relativedelta(minutes=1)).strftime('%Y-%m-%d %H:%M:%S') + t2 = (now + relativedelta(minutes=1, seconds=5)).strftime('%Y-%m-%d %H:%M:%S') + t3 = (now + relativedelta(minutes=1, seconds=10)).strftime('%Y-%m-%d %H:%M:%S') + self.create(cr, uid, dict(JOB, name='test_3 _80_seconds A', function='_80_seconds', nextcall=t1)) + self.create(cr, uid, dict(JOB, name='test_3 _20_seconds B', function='_20_seconds', nextcall=t2)) + self.create(cr, uid, dict(JOB, name='test_3 _20_seconds C', function='_20_seconds', nextcall=t3)) + + # This test assumes 4 cron threads. + def test_00(self, cr, uid): + self.test_00_set = set() + now = datetime.now() + t1 = (now + relativedelta(minutes=1)).strftime('%Y-%m-%d %H:%M:%S') + t2 = (now + relativedelta(minutes=1, seconds=5)).strftime('%Y-%m-%d %H:%M:%S') + t3 = (now + relativedelta(minutes=1, seconds=10)).strftime('%Y-%m-%d %H:%M:%S') + self.create(cr, uid, dict(JOB, name='test_00 _20_seconds_A', function='_20_seconds_A', nextcall=t1)) + self.create(cr, uid, dict(JOB, name='test_00 _20_seconds_B', function='_20_seconds_B', nextcall=t2)) + self.create(cr, uid, dict(JOB, name='test_00 _20_seconds_C', function='_20_seconds_C', nextcall=t3)) + + def _expect(self, cr, uid, to_add, to_sleep, to_expect_in, to_expect_out): + assert self.test_00_set == to_expect_in + self.test_00_set.add(to_add) + time.sleep(to_sleep) + self.test_00_set.discard(to_add) + assert self.test_00_set == to_expect_out + + def _20_seconds_A(self, cr, uid): + self._expect(cr, uid, 'A', 20, set(), set(['B', 'C'])) + + def _20_seconds_B(self, cr, uid): + self._expect(cr, uid, 'B', 20, set('A'), set('C')) + + def _20_seconds_C(self, cr, uid): + self._expect(cr, uid, 'C', 20, set(['A', 'B']), set()) + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: + diff --git a/openerp/addons/base/test/test_ir_cron.yml b/openerp/addons/base/test/test_ir_cron.yml new file mode 100644 index 00000000000..16d648e1c30 --- /dev/null +++ b/openerp/addons/base/test/test_ir_cron.yml @@ -0,0 +1,61 @@ +- + Test the cron jobs scheduling. +- + Disable the existing cron jobs if any during the tests. +- + !python {model: ir.cron }: | + # For this test to work, as it involves multiple database cursors, + # we have to commit changes. But YAML tests must be rollbacked, so + # the final database state is left untouched. So we have to be a bit + # ugly here: use our own cursor, commit, and clean after ourselves. + # We also pass around some ids using setattr/delattr, and we have to + # rollback the previous tests otherwise we won't be able to touch the + # db. + # Well, this should probably be a standalone, or regular unit test, + # instead of using the YAML infrastructure. + cr.rollback() + our_cr = self.pool.db.cursor() + try: + ids = self.search(our_cr, uid, [], {}) + setattr(self, 'saved_ids', ids) + self.write(our_cr, uid, ids, {'active': False}, {}) + our_cr.commit() + finally: + our_cr.close() +- + Three concurrent jobs started with a slight time gap. Assume 4 cron threads. + This will take about 2 minutes. +- + !python {model: ir.cron }: | + # Pretend initialization is already done. We the use a try/finally + # to reset _init correctly. + self.pool._init = False + our_cr = self.pool.db.cursor() + try: + self.test_00(our_cr, uid) # this will commit using the passed cursor + import openerp.cron + openerp.cron._thread_slots = 4 + # Wake up this db as soon as the master cron thread starts. + openerp.cron.schedule_wakeup(1, self.pool.db.dbname) + # Pretend to be the master thread, for 4 iterations. + openerp.cron.runner_body() + openerp.cron.runner_body() + openerp.cron.runner_body() + openerp.cron.runner_body() + finally: + self.pool._init = True + our_cr.close() +- + Clean after ourselves. +- + !python {model: ir.cron }: | + our_cr = self.pool.db.cursor() + try: + ids = [x for x in self.search(our_cr, uid, ['|', ('active', '=', True), ('active', '=', False)], {}) if x not in self.saved_ids] + self.unlink(our_cr, uid, ids, {}) + ids = self.saved_ids + delattr(self, 'saved_ids') + self.write(our_cr, uid, ids, {'active': True}, {}) + our_cr.commit() + finally: + our_cr.close() diff --git a/openerp/addons/base/test/test_osv_expression.yml b/openerp/addons/base/test/test_osv_expression.yml index 3a5e41dacc7..43fea5c16cf 100644 --- a/openerp/addons/base/test/test_osv_expression.yml +++ b/openerp/addons/base/test/test_osv_expression.yml @@ -177,6 +177,251 @@ res_ids = self.search(cr, uid, [('company_id.partner_id', 'not in', [])]) res_ids.sort() assert res_ids == all_ids, "Searching against empty set failed, returns %r" % res_ids +- + Test the '(not) like/in' behavior. res.partner and its parent_id column are used because + parent_id is a many2one, allowing to test the Null value, and there are actually some + null and non-null values in the demo data. +- + !python {model: res.partner }: | + partner_ids = self.search(cr, uid, []) + partner_ids.sort() + max_partner_id = max(partner_ids) + + # Grab test sample data without using a normal + # search domain, because we want to test these later, + # so we can't rely on them! + partners = self.browse(cr, uid, partner_ids) + with_parent = [] + without_parent = [] + with_website = [] + for x in partners: + if x.parent_id: + with_parent.append(x.id) + else: + without_parent.append(x.id) + if x.website: + with_website.append(x.id) + with_parent.sort() + without_parent.sort() + with_website.sort() + + # We treat null values differently than in SQL. For instance in SQL: + # SELECT id FROM res_partner WHERE parent_id NOT IN (0) + # will return only the records with non-null parent_id. + # SELECT id FROM res_partner WHERE parent_id IN (0) + # will return expectedly nothing (our ids always begin at 1). + # This means the union of those two results will give only some + # records, but not all present in database. + # + # When using domains and the ORM's search method, we think it is + # more intuitive that the union returns all the records, and that + # a domain like ('parent_id', 'not in', [0]) will return all + # the records. For instance, if you perform a search for the companies + # that don't have OpenERP has a parent company, you expect to find, + # among others, the companies that don't have parent company. + # + # ('parent_id', 'not in', [0]) must give the same result than + # ('parent_id', 'not in', []), i.e. a empty set or a set with non- + # existing values be treated similarly if we simply check that some + # existing value belongs to them. + + res_0 = self.search(cr, uid, [('parent_id', 'not like', 'probably_unexisting_name')]) # get all rows, included null parent_id + res_0.sort() + res_1 = self.search(cr, uid, [('parent_id', 'not in', [max_partner_id + 1])]) # get all rows, included null parent_id + res_1.sort() + res_2 = self.search(cr, uid, [('parent_id', 'not in', False)]) # get rows with not null parent_id, deprecated syntax + res_2.sort() + res_3 = self.search(cr, uid, [('parent_id', 'not in', [])]) # get all rows, included null parent_id + res_3.sort() + res_4 = self.search(cr, uid, [('parent_id', 'not in', [False])]) # get rows with not null parent_id + res_4.sort() + assert res_0 == partner_ids + assert res_1 == partner_ids + assert res_2 == with_parent + assert res_3 == partner_ids + assert res_4 == with_parent + # The results of these queries, when combined with queries 0..4 must + # give the whole set of ids. + res_5 = self.search(cr, uid, [('parent_id', 'like', 'probably_unexisting_name')]) + res_5.sort() + res_6 = self.search(cr, uid, [('parent_id', 'in', [max_partner_id + 1])]) + res_6.sort() + res_7 = self.search(cr, uid, [('parent_id', 'in', False)]) + res_7.sort() + res_8 = self.search(cr, uid, [('parent_id', 'in', [])]) + res_8.sort() + res_9 = self.search(cr, uid, [('parent_id', 'in', [False])]) + res_9.sort() + assert res_5 == [] + assert res_6 == [] + assert res_7 == without_parent + assert res_8 == [] + assert res_9 == without_parent + # These queries must return exactly the results than the queries 0..4, + # i.e. not ... in ... must be the same as ... not in ... . + res_10 = self.search(cr, uid, ['!', ('parent_id', 'like', 'probably_unexisting_name')]) + res_10.sort() + res_11 = self.search(cr, uid, ['!', ('parent_id', 'in', [max_partner_id + 1])]) + res_11.sort() + res_12 = self.search(cr, uid, ['!', ('parent_id', 'in', False)]) + res_12.sort() + res_13 = self.search(cr, uid, ['!', ('parent_id', 'in', [])]) + res_13.sort() + res_14 = self.search(cr, uid, ['!', ('parent_id', 'in', [False])]) + res_14.sort() + assert res_0 == res_10 + assert res_1 == res_11 + assert res_2 == res_12 + assert res_3 == res_13 + assert res_4 == res_14 + + # Testing many2one field is not enough, a regular char field is tested + # with in [] and must not return any result. + res_15 = self.search(cr, uid, [('website', 'in', [])]) + assert res_15 == [] + # not in [] must return everything. + res_16 = self.search(cr, uid, [('website', 'not in', [])]) + res_16.sort() + assert res_16 == partner_ids + + res_17 = self.search(cr, uid, [('website', 'not in', False)]) + res_17.sort() + assert res_17 == with_website +- + Property of the query (one2many not in False). +- + !python {model: res.currency }: | + ids = self.search(cr, uid, []) + referenced_companies = set([x.company_id.id for x in self.browse(cr, uid, ids)]) + companies = set(self.pool.get('res.company').search(cr, uid, [('currency_ids', 'not in', False)])) + assert referenced_companies == companies +- + Property of the query (one2many in False). +- + !python {model: res.currency }: | + ids = self.search(cr, uid, []) + referenced_companies = set([x.company_id.id for x in self.browse(cr, uid, ids)]) + unreferenced_companies = set(self.pool.get('res.company').search(cr, uid, [])).difference(referenced_companies) + companies = set(self.pool.get('res.company').search(cr, uid, [('currency_ids', 'in', False)])) + assert unreferenced_companies == companies +- + Equivalent queries. +- + !python {model: res.currency }: | + max_currency_id = max(self.search(cr, uid, [])) + res_0 = self.search(cr, uid, []) + res_1 = self.search(cr, uid, [('name', 'not like', 'probably_unexisting_name')]) + res_2 = self.search(cr, uid, [('id', 'not in', [max_currency_id + 1003])]) + res_3 = self.search(cr, uid, [('id', 'not in', [])]) + res_4 = self.search(cr, uid, [('id', 'not in', False)]) + res_0.sort() + res_1.sort() + res_2.sort() + res_3.sort() + res_4.sort() + assert res_0 == res_1 + assert res_0 == res_2 + assert res_0 == res_3 + assert res_0 == res_4 +- + Equivalent queries, integer and string. +- + !python {model: res.partner }: | + all_ids = self.search(cr, uid, []) + if len(all_ids) > 1: + one = all_ids[0] + record = self.browse(cr, uid, one) + others = all_ids[1:] + res_1 = self.search(cr, uid, [('id', '=', one)]) + # self.search(cr, uid, [('id', '!=', others)]) # not permitted + res_2 = self.search(cr, uid, [('id', 'not in', others)]) + res_3 = self.search(cr, uid, ['!', ('id', '!=', one)]) + res_4 = self.search(cr, uid, ['!', ('id', 'in', others)]) + # res_5 = self.search(cr, uid, [('id', 'in', one)]) # TODO make it permitted, just like for child_of + res_6 = self.search(cr, uid, [('id', 'in', [one])]) + res_7 = self.search(cr, uid, [('name', '=', record.name)]) + res_8 = self.search(cr, uid, [('name', 'in', [record.name])]) + # res_9 = self.search(cr, uid, [('name', 'in', record.name)]) # TODO + assert [one] == res_1 + assert [one] == res_2 + assert [one] == res_3 + assert [one] == res_4 + #assert [one] == res_5 + assert [one] == res_6 + assert [one] == res_7 +- + Need a company with a parent_id. +- + !record {model: res.company, id: ymltest_company3}: + name: Acme 3 +- + Need a company with a parent_id. +- + !record {model: res.company, id: ymltest_company4}: + name: Acme 4 + parent_id: ymltest_company3 +- + Equivalent queries, one2many. +- + !python {model: res.company }: | + # Search the company via its one2many (the one2many must point back at the company). + company = self.browse(cr, uid, ref('ymltest_company3')) + max_currency_id = max(self.pool.get('res.currency').search(cr, uid, [])) + currency_ids1 = self.pool.get('res.currency').search(cr, uid, [('name', 'not like', 'probably_unexisting_name')]) + currency_ids2 = self.pool.get('res.currency').search(cr, uid, [('id', 'not in', [max_currency_id + 1003])]) + currency_ids3 = self.pool.get('res.currency').search(cr, uid, [('id', 'not in', [])]) + assert currency_ids1 == currency_ids2 == currency_ids3, 'All 3 results should have be the same: all currencies' + default_company = self.browse(cr, uid, 1) + # one2many towards same model + res_1 = self.search(cr, uid, [('child_ids', 'in', [x.id for x in company.child_ids])]) # any company having a child of company3 as child + res_2 = self.search(cr, uid, [('child_ids', 'in', [company.child_ids[0].id])]) # any company having the first child of company3 as child + # one2many towards another model + res_3 = self.search(cr, uid, [('currency_ids', 'in', [x.id for x in default_company.currency_ids])]) # companies having a currency of main company + res_4 = self.search(cr, uid, [('currency_ids', 'in', [default_company.currency_ids[0].id])]) # companies having first currency of main company + res_5 = self.search(cr, uid, [('currency_ids', 'in', default_company.currency_ids[0].id)]) # companies having first currency of main company + # res_6 = self.search(cr, uid, [('currency_ids', 'in', [default_company.currency_ids[0].name])]) # TODO + res_7 = self.search(cr, uid, [('currency_ids', '=', default_company.currency_ids[0].name)]) + res_8 = self.search(cr, uid, [('currency_ids', 'like', default_company.currency_ids[0].name)]) + res_9 = self.search(cr, uid, [('currency_ids', 'like', 'probably_unexisting_name')]) + # self.search(cr, uid, [('currency_ids', 'unexisting_op', 'probably_unexisting_name')]) # TODO expected exception + assert res_1 == [ref('ymltest_company3')] + assert res_2 == [ref('ymltest_company3')] + assert res_3 == [1] + assert res_4 == [1] + assert res_5 == [1] + assert res_7 == [1] + assert res_8 == [1] + assert res_9 == [] + + # get the companies referenced by some currency (this is normally the main company) + res_10 = self.search(cr, uid, [('currency_ids', 'not like', 'probably_unexisting_name')]) + res_11 = self.search(cr, uid, [('currency_ids', 'not in', [max_currency_id + 1])]) + res_12 = self.search(cr, uid, [('currency_ids', 'not in', False)]) + res_13 = self.search(cr, uid, [('currency_ids', 'not in', [])]) + res_10.sort() + res_11.sort() + res_12.sort() + res_13.sort() + assert res_10 == res_11 + assert res_10 == res_12 + assert res_10 == res_13 + + # child_of x returns x and its children (direct or not). + company = self.browse(cr, uid, ref('ymltest_company3')) + expected = [ref('ymltest_company3'), ref('ymltest_company4')] + expected.sort() + res_1 = self.search(cr, uid, [('id', 'child_of', [ref('ymltest_company3')])]) + res_1.sort() + res_2 = self.search(cr, uid, [('id', 'child_of', ref('ymltest_company3'))]) + res_2.sort() + res_3 = self.search(cr, uid, [('id', 'child_of', [company.name])]) + res_3.sort() + res_4 = self.search(cr, uid, [('id', 'child_of', company.name)]) + res_4.sort() + assert res_1 == expected + assert res_2 == expected + assert res_3 == expected + assert res_4 == expected - Verify that normalize_domain() works. - @@ -187,6 +432,72 @@ domain = [('x','in',['y','z']),('a.v','=','e'),'|','|',('a','=','b'),'!',('c','>','d'),('e','!=','f'),('g','=','h')] norm_domain = ['&','&','&'] + domain assert norm_domain == expression.normalize(domain), "Non-normalized domains should be properly normalized" +- + Unaccent. Create a company with an accent in its name. +- + !record {model: res.company, id: ymltest_unaccent_company}: + name: Hélène +- + Test the unaccent-enabled 'ilike'. +- + !python {model: res.company}: | + if self.pool.has_unaccent: + ids = self.search(cr, uid, [('name','ilike','Helene')], {}) + assert ids == [ref('ymltest_unaccent_company')] + ids = self.search(cr, uid, [('name','ilike','hélène')], {}) + assert ids == [ref('ymltest_unaccent_company')] + ids = self.search(cr, uid, [('name','not ilike','Helene')], {}) + assert ref('ymltest_unaccent_company') not in ids + ids = self.search(cr, uid, [('name','not ilike','hélène')], {}) + assert ref('ymltest_unaccent_company') not in ids +- + Check that =like/=ilike expressions (no wildcard variants of like/ilike) are working on an untranslated field. +- + !python {model: res.partner }: | + all_ids = self.search(cr, uid, [('name', '=like', 'A_e_or')]) + assert len(all_ids) == 1, "Must match one partner (Axelor), got %r"%all_ids + all_ids = self.search(cr, uid, [('name', '=ilike', 'm_____')]) + assert len(all_ids) == 1, "Must match *only* one partner (Maxtor), got %r"%all_ids +- + Check that =like/=ilike expressions (no wildcard variants of like/ilike) are working on translated field. +- + !python {model: res.country }: | + all_ids = self.search(cr, uid, [('name', '=like', 'Ind__')]) + assert len(all_ids) == 1, "Must match India only, got %r"%all_ids + all_ids = self.search(cr, uid, [('name', '=ilike', 'z%')]) + assert len(all_ids) == 3, "Must match only countries with names starting with Z (currently 3), got %r"%all_ids +- + Use the create_date column on res.country (which doesn't declare it in _columns). +- + !python {model: res.country }: | + ids = self.search(cr, uid, [('create_date', '<', '2001-01-01 12:00:00')]) +- + Verify that invalid expressions are refused, even for magic fields +- + !python {model: res.country }: | + try: + self.search(cr, uid, [('does_not_exist', '=', 'foo')]) + raise AssertionError('Invalid fields should not be accepted') + except ValueError: + pass + + try: + self.search(cr, uid, [('create_date', '>>', 'foo')]) + raise AssertionError('Invalid operators should not be accepted') + except ValueError: + pass + + import psycopg2 + try: + cr._default_log_exceptions = False + cr.execute('SAVEPOINT expression_failure_test') + self.search(cr, uid, [('create_date', '=', "1970-01-01'); --")]) + # if the above search gives no error, the operand was not escaped! + cr.execute('RELEASE SAVEPOINT expression_failure_test') + raise AssertionError('Operands should always be SQL escaped') + except psycopg2.DataError: + # Should give: 'DataError: invalid input syntax for type timestamp' or similar + cr.execute('ROLLBACK TO SAVEPOINT expression_failure_test') diff --git a/openerp/conf/__init__.py b/openerp/conf/__init__.py index 7de8070f9e2..c89ddf44734 100644 --- a/openerp/conf/__init__.py +++ b/openerp/conf/__init__.py @@ -28,8 +28,25 @@ parsing, configuration file loading and saving, ...) in this module and provide real Python variables, e.g. addons_paths is really a list of paths. +To initialize properly this module, openerp.tools.config.parse_config() +must be used. + """ import deprecation +# Maximum number of threads processing concurrently cron jobs. +max_cron_threads = 4 # Actually the default value here is meaningless, + # look at tools.config for the default value. + +# Paths to search for OpenERP addons. +addons_paths = [] + +# List of server-wide modules to load. Those modules are supposed to provide +# features not necessarily tied to a particular database. This is in contrast +# to modules that are always bound to a specific database when they are +# installed (i.e. the majority of OpenERP addons). This is set with the --load +# command-line option. +server_wide_modules = [] + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerp/cron.py b/openerp/cron.py new file mode 100644 index 00000000000..d24300b7f43 --- /dev/null +++ b/openerp/cron.py @@ -0,0 +1,212 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2011 OpenERP SA () +# +# 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 . +# +############################################################################## + +""" Cron jobs scheduling + +Cron jobs are defined in the ir_cron table/model. This module deals with all +cron jobs, for all databases of a single OpenERP server instance. + +It defines a single master thread that will spawn (a bounded number of) +threads to process individual cron jobs. + +The thread runs forever, checking every 60 seconds for new +'database wake-ups'. It maintains a heapq of database wake-ups. At each +wake-up, it will call ir_cron._run_jobs_multithread() for the given database. _run_jobs_multithread +will check the jobs defined in the ir_cron table and spawn accordingly threads +to process them. + +This module's behavior depends on the following configuration variable: +openerp.conf.max_cron_threads. + +""" + +import heapq +import logging +import threading +import time + +import openerp +import tools + +# Heapq of database wake-ups. Note that 'database wake-up' meaning is in +# the context of the cron management. This is not originally about loading +# a database, although having the database name in the queue will +# cause it to be loaded when the schedule time is reached, even if it was +# unloaded in the mean time. Normally a database's wake-up is cancelled by +# the RegistryManager when the database is unloaded - so this should not +# cause it to be reloaded. +# +# TODO: perhaps in the future we could consider a flag on ir.cron jobs +# that would cause database wake-up even if the database has not been +# loaded yet or was already unloaded (e.g. 'force_db_wakeup' or something) +# +# Each element is a triple (timestamp, database-name, boolean). The boolean +# specifies if the wake-up is canceled (so a wake-up can be canceled without +# relying on the heapq implementation detail; no need to remove the job from +# the heapq). +_wakeups = [] + +# Mapping of database names to the wake-up defined in the heapq, +# so that we can cancel the wake-up without messing with the heapq +# invariant: lookup the wake-up by database-name, then set +# its third element to True. +_wakeup_by_db = {} + +# Re-entrant lock to protect the above _wakeups and _wakeup_by_db variables. +# We could use a simple (non-reentrant) lock if the runner function below +# was more fine-grained, but we are fine with the loop owning the lock +# while spawning a few threads. +_wakeups_lock = threading.RLock() + +# Maximum number of threads allowed to process cron jobs concurrently. This +# variable is set by start_master_thread using openerp.conf.max_cron_threads. +_thread_slots = None + +# A (non re-entrant) lock to protect the above _thread_slots variable. +_thread_slots_lock = threading.Lock() + +_logger = logging.getLogger('cron') + +# Sleep duration limits - must not loop too quickly, but can't sleep too long +# either, because a new job might be inserted in ir_cron with a much sooner +# execution date than current known ones. We won't see it until we wake! +MAX_SLEEP = 60 # 1 min +MIN_SLEEP = 1 # 1 sec + +# Dummy wake-up timestamp that can be used to force a database wake-up asap +WAKE_UP_NOW = 1 + +def get_thread_slots(): + """ Return the number of available thread slots """ + return _thread_slots + + +def release_thread_slot(): + """ Increment the number of available thread slots """ + global _thread_slots + with _thread_slots_lock: + _thread_slots += 1 + + +def take_thread_slot(): + """ Decrement the number of available thread slots """ + global _thread_slots + with _thread_slots_lock: + _thread_slots -= 1 + + +def cancel(db_name): + """ Cancel the next wake-up of a given database, if any. + + :param db_name: database name for which the wake-up is canceled. + + """ + _logger.debug("Cancel next wake-up for database '%s'.", db_name) + with _wakeups_lock: + if db_name in _wakeup_by_db: + _wakeup_by_db[db_name][2] = True + + +def cancel_all(): + """ Cancel all database wake-ups. """ + _logger.debug("Cancel all database wake-ups") + global _wakeups + global _wakeup_by_db + with _wakeups_lock: + _wakeups = [] + _wakeup_by_db = {} + + +def schedule_wakeup(timestamp, db_name): + """ Schedule a new wake-up for a database. + + If an earlier wake-up is already defined, the new wake-up is discarded. + If another wake-up is defined, that wake-up is discarded and the new one + is scheduled. + + :param db_name: database name for which a new wake-up is scheduled. + :param timestamp: when the wake-up is scheduled. + + """ + if not timestamp: + return + with _wakeups_lock: + if db_name in _wakeup_by_db: + task = _wakeup_by_db[db_name] + if not task[2] and timestamp > task[0]: + # existing wakeup is valid and occurs earlier than new one + return + task[2] = True # cancel existing task + task = [timestamp, db_name, False] + heapq.heappush(_wakeups, task) + _wakeup_by_db[db_name] = task + _logger.debug("Wake-up scheduled for database '%s' @ %s", db_name, + 'NOW' if timestamp == WAKE_UP_NOW else timestamp) + +def runner(): + """Neverending function (intended to be run in a dedicated thread) that + checks every 60 seconds the next database wake-up. TODO: make configurable + """ + while True: + runner_body() + +def runner_body(): + with _wakeups_lock: + while _wakeups and _wakeups[0][0] < time.time() and get_thread_slots(): + task = heapq.heappop(_wakeups) + timestamp, db_name, canceled = task + if canceled: + continue + del _wakeup_by_db[db_name] + registry = openerp.pooler.get_pool(db_name) + if not registry._init: + _logger.debug("Database '%s' wake-up! Firing multi-threaded cron job processing", db_name) + registry['ir.cron']._run_jobs_multithread() + amount = MAX_SLEEP + with _wakeups_lock: + # Sleep less than MAX_SLEEP if the next known wake-up will happen before that. + if _wakeups and get_thread_slots(): + amount = min(MAX_SLEEP, max(MIN_SLEEP, _wakeups[0][0] - time.time())) + _logger.debug("Going to sleep for %ss", amount) + time.sleep(amount) + +def start_master_thread(): + """ Start the above runner function in a daemon thread. + + The thread is a typical daemon thread: it will never quit and must be + terminated when the main process exits - with no consequence (the processing + threads it spawns are not marked daemon). + + """ + global _thread_slots + _thread_slots = openerp.conf.max_cron_threads + db_maxconn = tools.config['db_maxconn'] + if _thread_slots >= tools.config.get('db_maxconn', 64): + _logger.warning("Connection pool size (%s) is set lower than max number of cron threads (%s), " + "this may cause trouble if you reach that number of parallel cron tasks.", + db_maxconn, _thread_slots) + t = threading.Thread(target=runner, name="openerp.cron.master_thread") + t.setDaemon(True) + t.start() + _logger.debug("Master cron daemon started!") + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerp/exceptions.py b/openerp/exceptions.py new file mode 100644 index 00000000000..d12910c3448 --- /dev/null +++ b/openerp/exceptions.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2011 OpenERP s.a. (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +""" OpenERP core exceptions. + +This module defines a few exception types. Those types are understood by the +RPC layer. Any other exception type bubbling until the RPC layer will be +treated as a 'Server error'. + +""" + +class Warning(Exception): + pass + +class AccessDenied(Exception): + """ Login/password error. No message, no traceback. """ + def __init__(self): + super(AccessDenied, self).__init__('AccessDenied.') + self.traceback = ('', '', '') + +class AccessError(Exception): + """ Access rights error. """ + +class DeferredException(Exception): + """ Exception object holding a traceback for asynchronous reporting. + + Some RPC calls (database creation and report generation) happen with + an initial request followed by multiple, polling requests. This class + is used to store the possible exception occuring in the thread serving + the first request, and is then sent to a polling request. + + ('Traceback' is misleading, this is really a exc_info() triple.) + """ + def __init__(self, msg, tb): + self.message = msg + self.traceback = tb + self.args = (msg, tb) + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerp/modules/db.py b/openerp/modules/db.py index 25ce7283c97..6e6dd64b13c 100644 --- a/openerp/modules/db.py +++ b/openerp/modules/db.py @@ -21,6 +21,7 @@ ############################################################################## import openerp.modules +import logging def is_initialized(cr): """ Check if a database has been initialized for the ORM. @@ -40,6 +41,10 @@ def initialize(cr): """ f = openerp.modules.get_module_resource('base', 'base.sql') + if not f: + m = "File not found: 'base.sql' (provided by module 'base')." + logging.getLogger('init').critical(m) + raise IOError(m) base_sql_file = openerp.tools.misc.file_open(f) try: cr.execute(base_sql_file.read()) @@ -118,4 +123,14 @@ def create_categories(cr, categories): categories = categories[1:] return p_id +def has_unaccent(cr): + """ Test if the database has an unaccent function. + + The unaccent is supposed to be provided by the PostgreSQL unaccent contrib + module but any similar function will be picked by OpenERP. + + """ + cr.execute("SELECT proname FROM pg_proc WHERE proname='unaccent'") + return len(cr.fetchall()) > 0 + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerp/modules/graph.py b/openerp/modules/graph.py index 078d23c235b..539dda25b50 100644 --- a/openerp/modules/graph.py +++ b/openerp/modules/graph.py @@ -58,16 +58,16 @@ class Graph(dict): """ - def add_node(self, name, deps): + def add_node(self, name, info): max_depth, father = 0, None - for n in [Node(x, self) for x in deps]: + for n in [Node(x, self, None) for x in info['depends']]: if n.depth >= max_depth: father = n max_depth = n.depth if father: - return father.add_child(name) + return father.add_child(name, info) else: - return Node(name, self) + return Node(name, self, info) def update_from_db(self, cr): if not len(self): @@ -120,7 +120,7 @@ class Graph(dict): continue later.clear() current.remove(package) - node = self.add_node(package, deps) + node = self.add_node(package, info) node.data = info for kind in ('init', 'demo', 'update'): if package in tools.config[kind] or 'all' in tools.config[kind] or kind in force: @@ -154,12 +154,13 @@ class Graph(dict): class Singleton(object): - def __new__(cls, name, graph): + def __new__(cls, name, graph, info): if name in graph: inst = graph[name] else: inst = object.__new__(cls) inst.name = name + inst.info = info graph[name] = inst return inst @@ -167,19 +168,21 @@ class Singleton(object): class Node(Singleton): """ One module in the modules dependency graph. - Node acts as a per-module singleton. + Node acts as a per-module singleton. A node is constructed via + Graph.add_module() or Graph.add_modules(). Some of its fields are from + ir_module_module (setted by Graph.update_from_db()). """ - def __init__(self, name, graph): + def __init__(self, name, graph, info): self.graph = graph if not hasattr(self, 'children'): self.children = [] if not hasattr(self, 'depth'): self.depth = 0 - def add_child(self, name): - node = Node(name, self.graph) + def add_child(self, name, info): + node = Node(name, self.graph, info) node.depth = self.depth + 1 if node not in self.children: self.children.append(node) diff --git a/openerp/modules/loading.py b/openerp/modules/loading.py index 8fe6dd653bc..b06368ba1b2 100644 --- a/openerp/modules/loading.py +++ b/openerp/modules/loading.py @@ -158,7 +158,7 @@ def load_module_graph(cr, graph, status=None, perform_checks=True, skip_modules= logger.info('module %s: loading objects', package.name) migrations.migrate_module(package, 'pre') register_module_classes(package.name) - models = pool.instanciate(package.name, cr) + models = pool.load(cr, package) loaded_modules.append(package.name) if hasattr(package, 'init') or hasattr(package, 'update') or package.state in ('to install', 'to upgrade'): init_module_models(cr, package.name, models) @@ -273,8 +273,6 @@ def load_modules(db, force_demo=False, status=None, update_module=False): # This is a brand new pool, just created in pooler.get_db_and_pool() pool = pooler.get_pool(cr.dbname) - processed_modules = [] # for cleanup step after install - loaded_modules = [] # to avoid double loading report = tools.assertion_report() if 'base' in tools.config['update'] or 'all' in tools.config['update']: cr.execute("update ir_module_module set state=%s where name=%s and state=%s", ('to upgrade', 'base', 'installed')) @@ -285,8 +283,10 @@ def load_modules(db, force_demo=False, status=None, update_module=False): if not graph: logger.notifyChannel('init', netsvc.LOG_CRITICAL, 'module base cannot be loaded! (hint: verify addons-path)') raise osv.osv.except_osv(_('Could not load base module'), _('module base cannot be loaded! (hint: verify addons-path)')) - loaded, processed = load_module_graph(cr, graph, status, perform_checks=(not update_module), report=report) - processed_modules.extend(processed) + + # processed_modules: for cleanup step after install + # loaded_modules: to avoid double loading + loaded_modules, processed_modules = load_module_graph(cr, graph, status, perform_checks=(not update_module), report=report) if tools.config['load_language']: for lang in tools.config['load_language'].split(','): @@ -339,16 +339,16 @@ def load_modules(db, force_demo=False, status=None, update_module=False): cr.execute("""select model,name from ir_model where id NOT IN (select distinct model_id from ir_model_access)""") for (model, name) in cr.fetchall(): model_obj = pool.get(model) - if model_obj and not isinstance(model_obj, osv.osv.osv_memory): - logger.notifyChannel('init', netsvc.LOG_WARNING, 'object %s (%s) has no access rules!' % (model, name)) + if model_obj and not model_obj.is_transient(): + logger.notifyChannel('init', netsvc.LOG_WARNING, 'Model %s (%s) has no access rules!' % (model, name)) # Temporary warning while we remove access rights on osv_memory objects, as they have # been replaced by owner-only access rights cr.execute("""select distinct mod.model, mod.name from ir_model_access acc, ir_model mod where acc.model_id = mod.id""") for (model, name) in cr.fetchall(): model_obj = pool.get(model) - if isinstance(model_obj, osv.osv.osv_memory) and not isinstance(model_obj, osv.osv.osv): - logger.notifyChannel('init', netsvc.LOG_WARNING, 'In-memory object %s (%s) should not have explicit access rules!' % (model, name)) + if model_obj and model_obj.is_transient(): + logger.notifyChannel('init', netsvc.LOG_WARNING, 'The transient model %s (%s) should not have explicit access rules!' % (model, name)) cr.execute("SELECT model from ir_model") for (model,) in cr.fetchall(): @@ -356,7 +356,7 @@ def load_modules(db, force_demo=False, status=None, update_module=False): if obj: obj._check_removed_columns(cr, log=True) else: - logger.notifyChannel('init', netsvc.LOG_WARNING, "Model %s is referenced but not present in the orm pool!" % model) + logger.notifyChannel('init', netsvc.LOG_WARNING, "Model %s is declared but cannot be loaded! (Perhaps a module was partially removed or renamed)" % model) # Cleanup orphan records pool.get('ir.model.data')._process_end(cr, 1, processed_modules) diff --git a/openerp/modules/module.py b/openerp/modules/module.py index 1514e836dd8..b40e186e9a1 100644 --- a/openerp/modules/module.py +++ b/openerp/modules/module.py @@ -31,7 +31,6 @@ import openerp.osv as osv import openerp.tools as tools import openerp.tools.osutil as osutil from openerp.tools.safe_eval import safe_eval as eval -import openerp.pooler as pooler from openerp.tools.translate import _ import openerp.netsvc as netsvc @@ -58,6 +57,11 @@ loaded = [] logger = netsvc.Logger() def initialize_sys_path(): + """ Add all addons paths in sys.path. + + This ensures something like ``import crm`` works even if the addons are + not in the PYTHONPATH. + """ global ad_paths if ad_paths: @@ -250,6 +254,8 @@ def load_information_from_description_file(module): info['license'] = info.get('license') or 'AGPL-3' info.setdefault('installable', True) info.setdefault('active', False) + # If the following is provided, it is called after the module is --loaded. + info.setdefault('post_load', None) for kind in ['data', 'demo', 'test', 'init_xml', 'update_xml', 'demo_xml']: info.setdefault(kind, []) @@ -271,7 +277,6 @@ def init_module_models(cr, module_name, obj_list): TODO better explanation of _auto_init and init. """ - logger.notifyChannel('init', netsvc.LOG_INFO, 'module %s: creating or updating database tables' % module_name) todo = [] @@ -290,23 +295,22 @@ def init_module_models(cr, module_name, obj_list): t[1](cr, *t[2]) cr.commit() +# Import hook to write a addon m in both sys.modules['m'] and +# sys.modules['openerp.addons.m']. Otherwise it could be loaded twice +# if imported twice using different names. +#class MyImportHook(object): +# def find_module(self, module_name, package_path): +# print ">>>", module_name, package_path +# def load_module(self, module_name): +# raise ImportError("Restricted") -def load_module(module_name): - """ Load a Python module found on the addons paths.""" - fm = imp.find_module(module_name, ad_paths) - try: - imp.load_module(module_name, *fm) - finally: - if fm[0]: - fm[0].close() - +#sys.meta_path.append(MyImportHook()) def register_module_classes(m): """ Register module named m, if not already registered. - This will load the module and register all of its models. (Actually, the - explicit constructor call of each of the models inside the module will - register them.) + This loads the module and register all of its models, thanks to either + the MetaModel metaclass, or the explicit instantiation of the model. """ @@ -326,7 +330,7 @@ def register_module_classes(m): try: zip_mod_path = mod_path + '.zip' if not os.path.isfile(zip_mod_path): - load_module(m) + __import__(m) else: zimp = zipimport.zipimporter(zip_mod_path) zimp.load_module(m) diff --git a/openerp/modules/registry.py b/openerp/modules/registry.py index 072082db000..72cd4498cfa 100644 --- a/openerp/modules/registry.py +++ b/openerp/modules/registry.py @@ -22,10 +22,16 @@ """ Models registries. """ +import threading + +import logging import openerp.sql_db import openerp.osv.orm - +import openerp.cron +import openerp.tools +import openerp.modules.db +import openerp.tools.config class Registry(object): """ Model registry for a particular database. @@ -44,6 +50,14 @@ class Registry(object): self.db_name = db_name self.db = openerp.sql_db.db_connect(db_name) + cr = self.db.cursor() + has_unaccent = openerp.modules.db.has_unaccent(cr) + if openerp.tools.config['unaccent'] and not has_unaccent: + logger = logging.getLogger('unaccent') + logger.warning("The option --unaccent was given but no unaccent() function was found in database.") + self.has_unaccent = openerp.tools.config['unaccent'] and has_unaccent + cr.close() + def do_parent_store(self, cr): for o in self._init_parent: self.get(o)._parent_store_compute(cr) @@ -65,28 +79,42 @@ class Registry(object): """ Return a model for a given name or raise KeyError if it doesn't exist.""" return self.models[model_name] - def instanciate(self, module, cr): - """ Instanciate all the classes of a given module for a particular db.""" + def load(self, cr, module): + """ Load a given module in the registry. + + At the Python level, the modules are already loaded, but not yet on a + per-registry level. This method populates a registry with the given + modules, i.e. it instanciates all the classes of a the given module + and registers them in the registry. + + """ res = [] - # Instantiate registered classes (via metamodel discovery or via explicit - # constructor call), and add them to the pool. - for cls in openerp.osv.orm.MetaModel.module_to_models.get(module, []): - res.append(cls.createInstance(self, cr)) + # Instantiate registered classes (via the MetaModel automatic discovery + # or via explicit constructor call), and add them to the pool. + for cls in openerp.osv.orm.MetaModel.module_to_models.get(module.name, []): + res.append(cls.create_instance(self, cr)) return res + def schedule_cron_jobs(self): + """ Make the cron thread care about this registry/database jobs. + This will initiate the cron thread to check for any pending jobs for + this registry/database as soon as possible. Then it will continuously + monitor the ir.cron model for future jobs. See openerp.cron for + details. + """ + openerp.cron.schedule_wakeup(openerp.cron.WAKE_UP_NOW, self.db.dbname) + def clear_caches(self): """ Clear the caches - This clears the caches associated to methods decorated with ``tools.ormcache`` or ``tools.ormcache_multi`` for all the models. """ for model in self.models.itervalues(): model.clear_caches() - class RegistryManager(object): """ Model registries manager. @@ -94,24 +122,22 @@ class RegistryManager(object): registries (essentially database connection/model registry pairs). """ - # Mapping between db name and model registry. # Accessed through the methods below. registries = {} - + registries_lock = threading.RLock() @classmethod def get(cls, db_name, force_demo=False, status=None, update_module=False, pooljobs=True): """ Return a registry for a given database name.""" - - if db_name in cls.registries: - registry = cls.registries[db_name] - else: - registry = cls.new(db_name, force_demo, status, - update_module, pooljobs) - return registry - + with cls.registries_lock: + if db_name in cls.registries: + registry = cls.registries[db_name] + else: + registry = cls.new(db_name, force_demo, status, + update_module, pooljobs) + return registry @classmethod def new(cls, db_name, force_demo=False, status=None, @@ -121,47 +147,64 @@ class RegistryManager(object): The (possibly) previous registry for that database name is discarded. """ - import openerp.modules - registry = Registry(db_name) + with cls.registries_lock: + registry = Registry(db_name) - # Initializing a registry will call general code which will in turn - # call registries.get (this object) to obtain the registry being - # initialized. Make it available in the registries dictionary then - # remove it if an exception is raised. - cls.delete(db_name) - cls.registries[db_name] = registry - try: - # This should be a method on Registry - openerp.modules.load_modules(registry.db, force_demo, status, update_module) - except Exception: - del cls.registries[db_name] - raise + # Initializing a registry will call general code which will in turn + # call registries.get (this object) to obtain the registry being + # initialized. Make it available in the registries dictionary then + # remove it if an exception is raised. + cls.delete(db_name) + cls.registries[db_name] = registry + try: + # This should be a method on Registry + openerp.modules.load_modules(registry.db, force_demo, status, update_module) + except Exception: + del cls.registries[db_name] + raise - cr = registry.db.cursor() - try: - registry.do_parent_store(cr) - registry.get('ir.actions.report.xml').register_all(cr) - cr.commit() - finally: - cr.close() + cr = registry.db.cursor() + try: + registry.do_parent_store(cr) + registry.get('ir.actions.report.xml').register_all(cr) + cr.commit() + finally: + cr.close() - if pooljobs: - registry.get('ir.cron').restart(registry.db.dbname) - - return registry + if pooljobs: + registry.schedule_cron_jobs() + return registry @classmethod def delete(cls, db_name): - """ Delete the registry linked to a given database. """ - if db_name in cls.registries: - del cls.registries[db_name] + """Delete the registry linked to a given database. + + This also cleans the associated caches. For good measure this also + cancels the associated cron job. But please note that the cron job can + be running and take some time before ending, and that you should not + remove a registry if it can still be used by some thread. So it might + be necessary to call yourself openerp.cron.Agent.cancel(db_name) and + and join (i.e. wait for) the thread. + """ + with cls.registries_lock: + if db_name in cls.registries: + cls.registries[db_name].clear_caches() + del cls.registries[db_name] + openerp.cron.cancel(db_name) + @classmethod + def delete_all(cls): + """Delete all the registries. """ + with cls.registries_lock: + for db_name in cls.registries.keys(): + cls.delete(db_name) + @classmethod def clear_caches(cls, db_name): - """ Clear the caches + """Clear caches This clears the caches associated to methods decorated with ``tools.ormcache`` or ``tools.ormcache_multi`` for all the models @@ -170,8 +213,9 @@ class RegistryManager(object): This method is given to spare you a ``RegistryManager.get(db_name)`` that would loads the given database if it was not already loaded. """ - if db_name in cls.registries: - cls.registries[db_name].clear_caches() + with cls.registries_lock: + if db_name in cls.registries: + cls.registries[db_name].clear_caches() -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: \ No newline at end of file diff --git a/openerp/netsvc.py b/openerp/netsvc.py index 359813e7d41..1d0b2a25726 100644 --- a/openerp/netsvc.py +++ b/openerp/netsvc.py @@ -21,7 +21,6 @@ ############################################################################## import errno -import heapq import logging import logging.handlers import os @@ -31,12 +30,14 @@ import socket import sys import threading import time +import traceback import types from pprint import pformat # TODO modules that import netsvc only for things from loglevels must be changed to use loglevels. from loglevels import * import tools +import openerp def close_socket(sock): """ Closes a socket instance cleanly @@ -60,20 +61,22 @@ def close_socket(sock): #.apidoc title: Common Services: netsvc #.apidoc module-mods: member-order: bysource +def abort_response(dummy_1, description, dummy_2, details): + # TODO Replace except_{osv,orm} with these directly. + if description == 'AccessError': + raise openerp.exceptions.AccessError(details) + else: + raise openerp.exceptions.Warning(details) + class Service(object): """ Base class for *Local* services Functionality here is trusted, no authentication. """ _services = {} - def __init__(self, name, audience=''): + def __init__(self, name): Service._services[name] = self self.__name = name - self._methods = {} - - def joinGroup(self, name): - raise Exception("No group for local services") - #GROUPS.setdefault(name, {})[self.__name] = self @classmethod def exists(cls, name): @@ -84,75 +87,39 @@ class Service(object): if cls.exists(name): cls._services.pop(name) - def exportMethod(self, method): - if callable(method): - self._methods[method.__name__] = method +def LocalService(name): + # Special case for addons support, will be removed in a few days when addons + # are updated to directly use openerp.osv.osv.service. + if name == 'object_proxy': + return openerp.osv.osv.service - def abortResponse(self, error, description, origin, details): - if not tools.config['debug_mode']: - raise Exception("%s -- %s\n\n%s"%(origin, description, details)) - else: - raise - -class LocalService(object): - """ Proxy for local services. - - Any instance of this class will behave like the single instance - of Service(name) - """ - __logger = logging.getLogger('service') - def __init__(self, name): - self.__name = name - try: - self._service = Service._services[name] - for method_name, method_definition in self._service._methods.items(): - setattr(self, method_name, method_definition) - except KeyError, keyError: - self.__logger.error('This service does not exist: %s' % (str(keyError),) ) - raise - - def __call__(self, method, *params): - return getattr(self, method)(*params) + return Service._services[name] class ExportService(object): """ Proxy for exported services. - All methods here should take an AuthProxy as their first parameter. It - will be appended by the calling framework. - Note that this class has no direct proxy, capable of calling eservice.method(). Rather, the proxy should call - dispatch(method,auth,params) + dispatch(method, params) """ _services = {} - _groups = {} _logger = logging.getLogger('web-services') - - def __init__(self, name, audience=''): + + def __init__(self, name): ExportService._services[name] = self self.__name = name self._logger.debug("Registered an exported service: %s" % name) - def joinGroup(self, name): - ExportService._groups.setdefault(name, {})[self.__name] = self - @classmethod def getService(cls,name): return cls._services[name] - def dispatch(self, method, auth, params): + # Dispatch a RPC call w.r.t. the method name. The dispatching + # w.r.t. the service (this class) is done by OpenERPDispatcher. + def dispatch(self, method, params): raise Exception("stub dispatch at %s" % self.__name) - def new_dispatch(self,method,auth,params): - raise Exception("stub dispatch at %s" % self.__name) - - def abortResponse(self, error, description, origin, details): - if not tools.config['debug_mode']: - raise Exception("%s -- %s\n\n%s"%(origin, description, details)) - else: - raise - BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, _NOTHING, DEFAULT = range(10) #The background is set with 40 plus the number of the color, and the foreground with 30 #These are the sequences need to get colored ouput @@ -244,83 +211,6 @@ def init_alternative_logger(): logger.addHandler(handler) logger.setLevel(logging.ERROR) -class Agent(object): - """ Singleton that keeps track of cancellable tasks to run at a given - timestamp. - - The tasks are characterised by: - - * a timestamp - * the database on which the task run - * the function to call - * the arguments and keyword arguments to pass to the function - - Implementation details: - - - Tasks are stored as list, allowing the cancellation by setting - the timestamp to 0. - - A heapq is used to store tasks, so we don't need to sort - tasks ourself. - """ - __tasks = [] - __tasks_by_db = {} - _logger = logging.getLogger('netsvc.agent') - - @classmethod - def setAlarm(cls, function, timestamp, db_name, *args, **kwargs): - task = [timestamp, db_name, function, args, kwargs] - heapq.heappush(cls.__tasks, task) - cls.__tasks_by_db.setdefault(db_name, []).append(task) - - @classmethod - def cancel(cls, db_name): - """Cancel all tasks for a given database. If None is passed, all tasks are cancelled""" - cls._logger.debug("Cancel timers for %s db", db_name or 'all') - if db_name is None: - cls.__tasks, cls.__tasks_by_db = [], {} - else: - if db_name in cls.__tasks_by_db: - for task in cls.__tasks_by_db[db_name]: - task[0] = 0 - - @classmethod - def quit(cls): - cls.cancel(None) - - @classmethod - def runner(cls): - """Neverending function (intended to be ran in a dedicated thread) that - checks every 60 seconds tasks to run. TODO: make configurable - """ - current_thread = threading.currentThread() - while True: - while cls.__tasks and cls.__tasks[0][0] < time.time(): - task = heapq.heappop(cls.__tasks) - timestamp, dbname, function, args, kwargs = task - cls.__tasks_by_db[dbname].remove(task) - if not timestamp: - # null timestamp -> cancelled task - continue - current_thread.dbname = dbname # hack hack - cls._logger.debug("Run %s.%s(*%s, **%s)", function.im_class.__name__, function.func_name, args, kwargs) - delattr(current_thread, 'dbname') - task_thread = threading.Thread(target=function, name='netsvc.Agent.task', args=args, kwargs=kwargs) - # force non-daemon task threads (the runner thread must be daemon, and this property is inherited by default) - task_thread.setDaemon(False) - task_thread.start() - time.sleep(1) - time.sleep(60) - -def start_agent(): - agent_runner = threading.Thread(target=Agent.runner, name="netsvc.Agent.runner") - # the agent runner is a typical daemon thread, that will never quit and must be - # terminated when the main process exits - with no consequence (the processing - # threads it spawns are not marked daemon) - agent_runner.setDaemon(True) - agent_runner.start() - -import traceback - class Server: """ Generic interface for all servers with an event loop etc. Override this to impement http, net-rpc etc. servers. @@ -403,11 +293,6 @@ class Server: def _close_socket(self): close_socket(self.socket) -class OpenERPDispatcherException(Exception): - def __init__(self, exception, traceback): - self.exception = exception - self.traceback = traceback - def replace_request_password(args): # password is always 3rd argument in a request, we replace it in RPC logs # so it's easier to forward logs for diagnostics/debugging purposes... @@ -425,33 +310,47 @@ def log(title, msg, channel=logging.DEBUG_RPC, depth=None, fn=""): logger.log(channel, indent+line) indent=indent_after -class OpenERPDispatcher: - def log(self, title, msg, channel=logging.DEBUG_RPC, depth=None, fn=""): +def dispatch_rpc(service_name, method, params): + """ Handle a RPC call. + + This is pure Python code, the actual marshalling (from/to XML-RPC or + NET-RPC) is done in a upper layer. + """ + def _log(title, msg, channel=logging.DEBUG_RPC, depth=None, fn=""): log(title, msg, channel=channel, depth=depth, fn=fn) - def dispatch(self, service_name, method, params): - try: - auth = getattr(self, 'auth_provider', None) - logger = logging.getLogger('result') - start_time = end_time = 0 - if logger.isEnabledFor(logging.DEBUG_RPC_ANSWER): - self.log('service', tuple(replace_request_password(params)), depth=None, fn='%s.%s'%(service_name,method)) - if logger.isEnabledFor(logging.DEBUG_RPC): - start_time = time.time() - result = ExportService.getService(service_name).dispatch(method, auth, params) - if logger.isEnabledFor(logging.DEBUG_RPC): - end_time = time.time() - if not logger.isEnabledFor(logging.DEBUG_RPC_ANSWER): - self.log('service (%.3fs)' % (end_time - start_time), tuple(replace_request_password(params)), depth=1, fn='%s.%s'%(service_name,method)) - self.log('execution time', '%.3fs' % (end_time - start_time), channel=logging.DEBUG_RPC_ANSWER) - self.log('result', result, channel=logging.DEBUG_RPC_ANSWER) - return result - except Exception, e: - self.log('exception', tools.exception_to_unicode(e)) - tb = getattr(e, 'traceback', sys.exc_info()) - tb_s = "".join(traceback.format_exception(*tb)) - if tools.config['debug_mode'] and isinstance(tb[2], types.TracebackType): - import pdb - pdb.post_mortem(tb[2]) - raise OpenERPDispatcherException(e, tb_s) + try: + logger = logging.getLogger('result') + start_time = end_time = 0 + if logger.isEnabledFor(logging.DEBUG_RPC_ANSWER): + _log('service', tuple(replace_request_password(params)), depth=None, fn='%s.%s'%(service_name,method)) + if logger.isEnabledFor(logging.DEBUG_RPC): + start_time = time.time() + result = ExportService.getService(service_name).dispatch(method, params) + if logger.isEnabledFor(logging.DEBUG_RPC): + end_time = time.time() + if not logger.isEnabledFor(logging.DEBUG_RPC_ANSWER): + _log('service (%.3fs)' % (end_time - start_time), tuple(replace_request_password(params)), depth=1, fn='%s.%s'%(service_name,method)) + _log('execution time', '%.3fs' % (end_time - start_time), channel=logging.DEBUG_RPC_ANSWER) + _log('result', result, channel=logging.DEBUG_RPC_ANSWER) + return result + except openerp.exceptions.AccessError: + raise + except openerp.exceptions.AccessDenied: + raise + except openerp.exceptions.Warning: + raise + except openerp.exceptions.DeferredException, e: + _log('exception', tools.exception_to_unicode(e)) + post_mortem(e.traceback) + raise + except Exception, e: + _log('exception', tools.exception_to_unicode(e)) + post_mortem(sys.exc_info()) + raise + +def post_mortem(info): + if tools.config['debug_mode'] and isinstance(info[2], types.TracebackType): + import pdb + pdb.post_mortem(info[2]) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerp/osv/expression.py b/openerp/osv/expression.py index 54726a289f2..cb8cfea583f 100644 --- a/openerp/osv/expression.py +++ b/openerp/osv/expression.py @@ -20,17 +20,146 @@ # ############################################################################## +""" Domain expression processing + +The main duty of this module is to compile a domain expression into a SQL +query. A lot of things should be documented here, but as a first step in the +right direction, some tests in test_osv_expression.yml might give you some +additional information. + +For legacy reasons, a domain uses an inconsistent two-levels abstract syntax +(domains are regular Python data structures). At the first level, a domain +is an expression made of terms (sometimes called leaves) and (domain) operators +used in prefix notation. The available operators at this level are '!', '&', +and '|'. '!' is a unary 'not', '&' is a binary 'and', and '|' is a binary 'or'. +For instance, here is a possible domain. ( stands for an arbitrary term, +more on this later.) + + ['&', '!', , '|', , ] + +It is equivalent to this pseudo code using infix notation: + + (not ) and ( or ) + +The second level of syntax deals with the term representation. A term is +a triple of the form (left, operator, right). That is, a term uses an infix +notation, and the available operators, and possible left and right operands +differ with those of the previous level. Here is a possible term: + + ('company_id.name', '=', 'OpenERP') + +The left and right operand don't have the same possible values. The left +operand is field name (related to the model for which the domain applies). +Actually, the field name can use the dot-notation to traverse relationships. +The right operand is a Python value whose type should match the used operator +and field type. In the above example, a string is used because the name field +of a company has type string, and because we use the '=' operator. When +appropriate, a 'in' operator can be used, and thus the right operand should be +a list. + +Note: the non-uniform syntax could have been more uniform, but this would hide +an important limitation of the domain syntax. Say that the term representation +was ['=', 'company_id.name', 'OpenERP']. Used in a complete domain, this would +look like: + + ['!', ['=', 'company_id.name', 'OpenERP']] + +and you would be tempted to believe something like this would be possible: + + ['!', ['=', 'company_id.name', ['&', ..., ...]]] + +That is, a domain could be a valid operand. But this is not the case. A domain +is really limited to a two-level nature, and can not takes a recursive form: a +domain is not a valid second-level operand. + +Unaccent - Accent-insensitive search + +OpenERP will use the SQL function 'unaccent' when available for the 'ilike' and +'not ilike' operators, and enabled in the configuration. +Normally the 'unaccent' function is obtained from the PostgreSQL 'unaccent' +contrib module[0]. + + +..todo: The following explanation should be moved in some external installation + guide + +The steps to install the module might differ on specific PostgreSQL versions. +We give here some instruction for PostgreSQL 9.x on a Ubuntu system. + +Ubuntu doesn't come yet with PostgreSQL 9.x, so an alternative package source +is used. We use Martin Pitt's PPA available at ppa:pitti/postgresql[1]. See +[2] for instructions. Basically: + + > sudo add-apt-repository ppa:pitti/postgresql + > sudo apt-get update + +Once the package list is up-to-date, you have to install PostgreSQL 9.0 and +its contrib modules. + + > sudo apt-get install postgresql-9.0 postgresql-contrib-9.0 + +When you want to enable unaccent on some database: + + > psql9 -f /usr/share/postgresql/9.0/contrib/unaccent.sql + +Here 'psql9' is an alias for the newly installed PostgreSQL 9.0 tool, together +with the correct port if necessary (for instance if PostgreSQL 8.4 is running +on 5432). (Other aliases can be used for createdb and dropdb.) + + > alias psql9='/usr/lib/postgresql/9.0/bin/psql -p 5433' + +You can check unaccent is working: + + > psql9 -c"select unaccent('hélène')" + +Finally, to instruct OpenERP to really use the unaccent function, you have to +start the server specifying the --unaccent flag. + +[0] http://developer.postgresql.org/pgdocs/postgres/unaccent.html +[1] https://launchpad.net/~pitti/+archive/postgresql +[2] https://launchpad.net/+help/soyuz/ppa-sources-list.html + +""" + +import logging + from openerp.tools import flatten, reverse_enumerate import fields +import openerp.modules +from openerp.osv.orm import MAGIC_COLUMNS #.apidoc title: Domain Expressions +# Domain operators. NOT_OPERATOR = '!' OR_OPERATOR = '|' AND_OPERATOR = '&' +DOMAIN_OPERATORS = (NOT_OPERATOR, OR_OPERATOR, AND_OPERATOR) -TRUE_DOMAIN = [(1,'=',1)] -FALSE_DOMAIN = [(0,'=',1)] +# List of available term operators. It is also possible to use the '<>' +# operator, which is strictly the same as '!='; the later should be prefered +# for consistency. This list doesn't contain '<>' as it is simpified to '!=' +# by the normalize_operator() function (so later part of the code deals with +# only one representation). +# An internal (i.e. not available to the user) 'inselect' operator is also +# used. In this case its right operand has the form (subselect, params). +TERM_OPERATORS = ('=', '!=', '<=', '<', '>', '>=', '=?', '=like', '=ilike', + 'like', 'not like', 'ilike', 'not ilike', 'in', 'not in', + 'child_of') + +# A subset of the above operators, with a 'negative' semantic. When the +# expressions 'in NEGATIVE_TERM_OPERATORS' or 'not in NEGATIVE_TERM_OPERATORS' are used in the code +# below, this doesn't necessarily mean that any of those NEGATIVE_TERM_OPERATORS is +# legal in the processed term. +NEGATIVE_TERM_OPERATORS = ('!=', 'not like', 'not ilike', 'not in') + +TRUE_LEAF = (1, '=', 1) +FALSE_LEAF = (0, '=', 1) + +TRUE_DOMAIN = [TRUE_LEAF] +FALSE_DOMAIN = [FALSE_LEAF] + +_logger = logging.getLogger('expression') def normalize(domain): """Returns a normalized version of ``domain_expr``, where all implicit '&' operators @@ -45,10 +174,10 @@ def normalize(domain): op_arity = {NOT_OPERATOR: 1, AND_OPERATOR: 2, OR_OPERATOR: 2} for token in domain: if expected == 0: # more than expected, like in [A, B] - result[0:0] = ['&'] # put an extra '&' in front + result[0:0] = [AND_OPERATOR] # put an extra '&' in front expected = 1 result.append(token) - if isinstance(token, (list,tuple)): # domain term + if isinstance(token, (list, tuple)): # domain term expected -= 1 else: expected += op_arity.get(token, 0) - 1 @@ -57,7 +186,8 @@ def normalize(domain): def combine(operator, unit, zero, domains): """Returns a new domain expression where all domain components from ``domains`` - have been added together using the binary operator ``operator``. + have been added together using the binary operator ``operator``. The given + domains must be normalized. :param unit: the identity element of the domains "set" with regard to the operation performed by ``operator``, i.e the domain component ``i`` which, when @@ -69,6 +199,7 @@ def combine(operator, unit, zero, domains): combined with any domain ``x`` via ``operator``, yields ``z``. E.g. [(1,'=',1)] is the typical zero for OR_OPERATOR: as soon as you see it in a domain component the resulting domain is the zero. + :param domains: a list of normalized domains. """ result = [] count = 0 @@ -84,13 +215,130 @@ def combine(operator, unit, zero, domains): return result def AND(domains): - """ AND([D1,D2,...]) returns a domain representing D1 and D2 and ... """ + """AND([D1,D2,...]) returns a domain representing D1 and D2 and ... """ return combine(AND_OPERATOR, TRUE_DOMAIN, FALSE_DOMAIN, domains) def OR(domains): - """ OR([D1,D2,...]) returns a domain representing D1 or D2 or ... """ + """OR([D1,D2,...]) returns a domain representing D1 or D2 or ... """ return combine(OR_OPERATOR, FALSE_DOMAIN, TRUE_DOMAIN, domains) +def is_operator(element): + """Test whether an object is a valid domain operator. """ + return isinstance(element, basestring) and element in DOMAIN_OPERATORS + +# TODO change the share wizard to use this function. +def is_leaf(element, internal=False): + """ Test whether an object is a valid domain term. + + :param internal: allow or not the 'inselect' internal operator in the term. + This normally should be always left to False. + """ + INTERNAL_OPS = TERM_OPERATORS + ('inselect',) + return (isinstance(element, tuple) or isinstance(element, list)) \ + and len(element) == 3 \ + and (((not internal) and element[1] in TERM_OPERATORS + ('<>',)) \ + or (internal and element[1] in INTERNAL_OPS + ('<>',))) + +def normalize_leaf(left, operator, right): + """ Change a term's operator to some canonical form, simplifying later + processing. + """ + original = operator + operator = operator.lower() + if operator == '<>': + operator = '!=' + if isinstance(right, bool) and operator in ('in', 'not in'): + _logger.warning("The domain term '%s' should use the '=' or '!=' operator." % ((left, original, right),)) + operator = '=' if operator == 'in' else '!=' + if isinstance(right, (list, tuple)) and operator in ('=', '!='): + _logger.warning("The domain term '%s' should use the 'in' or 'not in' operator." % ((left, original, right),)) + operator = 'in' if operator == '=' else 'not in' + return left, operator, right + +def distribute_not(domain): + """ Distribute any '!' domain operators found inside a normalized domain. + + Because we don't use SQL semantic for processing a 'left not in right' + query (i.e. our 'not in' is not simply translated to a SQL 'not in'), + it means that a '! left in right' can not be simply processed + by __leaf_to_sql by first emitting code for 'left in right' then wrapping + the result with 'not (...)', as it would result in a 'not in' at the SQL + level. + + This function is thus responsible for pushing any '!' domain operators + inside the terms themselves. For example:: + + ['!','&',('user_id','=',4),('partner_id','in',[1,2])] + will be turned into: + ['|',('user_id','!=',4),('partner_id','not in',[1,2])] + + """ + def negate(leaf): + """Negates and returns a single domain leaf term, + using the opposite operator if possible""" + left, operator, right = leaf + mapping = { + '<': '>=', + '>': '<=', + '<=': '>', + '>=': '<', + '=': '!=', + '!=': '=', + } + if operator in ('in', 'like', 'ilike'): + operator = 'not ' + operator + return [(left, operator, right)] + if operator in ('not in', 'not like', 'not ilike'): + operator = operator[4:] + return [(left, operator, right)] + if operator in mapping: + operator = mapping[operator] + return [(left, operator, right)] + return [NOT_OPERATOR, (left, operator, right)] + def distribute_negate(domain): + """Negate the domain ``subtree`` rooted at domain[0], + leaving the rest of the domain intact, and return + (negated_subtree, untouched_domain_rest) + """ + if is_leaf(domain[0]): + return negate(domain[0]), domain[1:] + if domain[0] == AND_OPERATOR: + done1, todo1 = distribute_negate(domain[1:]) + done2, todo2 = distribute_negate(todo1) + return [OR_OPERATOR] + done1 + done2, todo2 + if domain[0] == OR_OPERATOR: + done1, todo1 = distribute_negate(domain[1:]) + done2, todo2 = distribute_negate(todo1) + return [AND_OPERATOR] + done1 + done2, todo2 + if not domain: + return [] + if domain[0] != NOT_OPERATOR: + return [domain[0]] + distribute_not(domain[1:]) + if domain[0] == NOT_OPERATOR: + done, todo = distribute_negate(domain[1:]) + return done + distribute_not(todo) + +def select_from_where(cr, select_field, from_table, where_field, where_ids, where_operator): + # todo: merge into parent query as sub-query + res = [] + if where_ids: + if where_operator in ['<','>','>=','<=']: + cr.execute('SELECT "%s" FROM "%s" WHERE "%s" %s %%s' % \ + (select_field, from_table, where_field, where_operator), + (where_ids[0],)) # TODO shouldn't this be min/max(where_ids) ? + res = [r[0] for r in cr.fetchall()] + else: # TODO where_operator is supposed to be 'in'? It is called with child_of... + for i in range(0, len(where_ids), cr.IN_MAX): + subids = where_ids[i:i+cr.IN_MAX] + cr.execute('SELECT "%s" FROM "%s" WHERE "%s" IN %%s' % \ + (select_field, from_table, where_field), (tuple(subids),)) + res.extend([r[0] for r in cr.fetchall()]) + return res + +def select_distinct_from_where_not_null(cr, select_field, from_table): + cr.execute('SELECT distinct("%s") FROM "%s" where "%s" is not null' % \ + (select_field, from_table, select_field)) + return [r[0] for r in cr.fetchall()] class expression(object): """ @@ -100,148 +348,124 @@ class expression(object): For more info: http://christophe-simonis-at-tiny.blogspot.com/2008/08/new-new-domain-notation.html """ - @classmethod - def _is_operator(cls, element): - return isinstance(element, (str, unicode)) and element in [AND_OPERATOR, OR_OPERATOR, NOT_OPERATOR] - - @classmethod - def _is_leaf(cls, element, internal=False): - OPS = ('=', '!=', '<>', '<=', '<', '>', '>=', '=?', '=like', '=ilike', 'like', 'not like', 'ilike', 'not ilike', 'in', 'not in', 'child_of') - INTERNAL_OPS = OPS + ('inselect',) - return (isinstance(element, tuple) or isinstance(element, list)) \ - and len(element) == 3 \ - and (((not internal) and element[1] in OPS) \ - or (internal and element[1] in INTERNAL_OPS)) - - def __execute_recursive_in(self, cr, s, f, w, ids, op, type): - # todo: merge into parent query as sub-query - res = [] - if ids: - if op in ['<','>','>=','<=']: - cr.execute('SELECT "%s"' \ - ' FROM "%s"' \ - ' WHERE "%s" %s %%s' % (s, f, w, op), (ids[0],)) - res.extend([r[0] for r in cr.fetchall()]) - else: - for i in range(0, len(ids), cr.IN_MAX): - subids = ids[i:i+cr.IN_MAX] - cr.execute('SELECT "%s"' \ - ' FROM "%s"' \ - ' WHERE "%s" IN %%s' % (s, f, w),(tuple(subids),)) - res.extend([r[0] for r in cr.fetchall()]) - else: - cr.execute('SELECT distinct("%s")' \ - ' FROM "%s" where "%s" is not null' % (s, f, s)), - res.extend([r[0] for r in cr.fetchall()]) - return res - - def __init__(self, exp): - # check if the expression is valid - if not reduce(lambda acc, val: acc and (self._is_operator(val) or self._is_leaf(val)), exp, True): - raise ValueError('Bad domain expression: %r' % (exp,)) - self.__exp = exp + def __init__(self, cr, uid, exp, table, context): + self.has_unaccent = openerp.modules.registry.RegistryManager.get(cr.dbname).has_unaccent self.__field_tables = {} # used to store the table to use for the sql generation. key = index of the leaf self.__all_tables = set() self.__joins = [] self.__main_table = None # 'root' table. set by parse() - self.__DUMMY_LEAF = (1, '=', 1) # a dummy leaf that must not be parsed or sql generated + # assign self.__exp with the normalized, parsed domain. + self.parse(cr, uid, distribute_not(normalize(exp)), table, context) + # TODO used only for osv_memory @property def exp(self): return self.__exp[:] - def parse(self, cr, uid, table, context): - """ transform the leafs of the expression """ - if not self.__exp: - return self + def parse(self, cr, uid, exp, table, context): + """ transform the leaves of the expression """ + self.__exp = exp + self.__main_table = table + self.__all_tables.add(table) - def _rec_get(ids, table, parent=None, left='id', prefix=''): - if table._parent_store and (not table.pool._init): -# TODO: Improve where joins are implemented for many with '.', replace by: -# doms += ['&',(prefix+'.parent_left','<',o.parent_right),(prefix+'.parent_left','>=',o.parent_left)] + def child_of_domain(left, ids, left_model, parent=None, prefix=''): + """Returns a domain implementing the child_of operator for [(left,child_of,ids)], + either as a range using the parent_left/right tree lookup fields (when available), + or as an expanded [(left,in,child_ids)]""" + if left_model._parent_store and (not left_model.pool._init): + # TODO: Improve where joins are implemented for many with '.', replace by: + # doms += ['&',(prefix+'.parent_left','<',o.parent_right),(prefix+'.parent_left','>=',o.parent_left)] doms = [] - for o in table.browse(cr, uid, ids, context=context): + for o in left_model.browse(cr, uid, ids, context=context): if doms: doms.insert(0, OR_OPERATOR) doms += [AND_OPERATOR, ('parent_left', '<', o.parent_right), ('parent_left', '>=', o.parent_left)] if prefix: - return [(left, 'in', table.search(cr, uid, doms, context=context))] + return [(left, 'in', left_model.search(cr, uid, doms, context=context))] return doms else: - def rg(ids, table, parent): + def recursive_children(ids, model, parent_field): if not ids: return [] - ids2 = table.search(cr, uid, [(parent, 'in', ids)], context=context) - return ids + rg(ids2, table, parent) - return [(left, 'in', rg(ids, table, parent or table._parent_name))] + ids2 = model.search(cr, uid, [(parent_field, 'in', ids)], context=context) + return ids + recursive_children(ids2, model, parent_field) + return [(left, 'in', recursive_children(ids, left_model, parent or left_model._parent_name))] - def child_of_right_to_ids(value): - """ Normalize a single id, or a string, or a list of ids to a list of ids. - - This function is always used with _rec_get() above, so it should be - called directly from _rec_get instead of repeatedly before _rec_get. - - """ + def to_ids(value, field_obj): + """Normalize a single id or name, or a list of those, into a list of ids""" + names = [] if isinstance(value, basestring): - return [x[0] for x in field_obj.name_search(cr, uid, value, [], 'ilike', context=context, limit=None)] + names = [value] + if value and isinstance(value, (tuple, list)) and isinstance(value[0], basestring): + names = value + if names: + return flatten([[x[0] for x in field_obj.name_search(cr, uid, n, [], 'ilike', context=context, limit=None)] \ + for n in names]) elif isinstance(value, (int, long)): return [value] - else: - return list(value) - - self.__main_table = table - self.__all_tables.add(table) + return list(value) i = -1 while i + 1 1: + if len(field_path) > 1: if field._type == 'many2one': - right = field_obj.search(cr, uid, [(fargs[1], operator, right)], context=context) - if right == []: - self.__exp[i] = ( 'id', '=', 0 ) - else: - self.__exp[i] = (fargs[0], 'in', right) + right = field_obj.search(cr, uid, [(field_path[1], operator, right)], context=context) + self.__exp[i] = (field_path[0], 'in', right) # Making search easier when there is a left operand as field.o2m or field.m2m - if field._type in ['many2many','one2many']: - right = field_obj.search(cr, uid, [(fargs[1], operator, right)], context=context) - right1 = table.search(cr, uid, [(fargs[0],'in', right)], context=context) - if right1 == []: - self.__exp[i] = ( 'id', '=', 0 ) - else: - self.__exp[i] = ('id', 'in', right1) + if field._type in ['many2many', 'one2many']: + right = field_obj.search(cr, uid, [(field_path[1], operator, right)], context=context) + right1 = table.search(cr, uid, [(field_path[0], 'in', right)], context=context) + self.__exp[i] = ('id', 'in', right1) - if not isinstance(field,fields.property): + if not isinstance(field, fields.property): continue if field._properties and not field.store: @@ -249,16 +473,16 @@ class expression(object): if not field._fnct_search: # the function field doesn't provide a search function and doesn't store # values in the database, so we must ignore it : we generate a dummy leaf - self.__exp[i] = self.__DUMMY_LEAF + self.__exp[i] = TRUE_LEAF else: subexp = field.search(cr, uid, table, left, [self.__exp[i]], context=context) if not subexp: - self.__exp[i] = self.__DUMMY_LEAF + self.__exp[i] = TRUE_LEAF else: # we assume that the expression is valid # we create a dummy leaf for forcing the parsing of the resulting expression self.__exp[i] = AND_OPERATOR - self.__exp.insert(i + 1, self.__DUMMY_LEAF) + self.__exp.insert(i + 1, TRUE_LEAF) for j, se in enumerate(subexp): self.__exp.insert(i + 2 + j, se) # else, the value of the field is store in the database, so we search on it @@ -266,11 +490,11 @@ class expression(object): elif field._type == 'one2many': # Applying recursivity on field(one2many) if operator == 'child_of': - ids2 = child_of_right_to_ids(right) + ids2 = to_ids(right, field_obj) if field._obj != working_table._name: - dom = _rec_get(ids2, field_obj, left=left, prefix=field._obj) + dom = child_of_domain(left, ids2, field_obj, prefix=field._obj) else: - dom = _rec_get(ids2, working_table, parent=left) + dom = child_of_domain('id', ids2, working_table, parent=left) self.__exp = self.__exp[:i] + dom + self.__exp[i+1:] else: @@ -282,7 +506,7 @@ class expression(object): if ids2: operator = 'in' else: - if not isinstance(right,list): + if not isinstance(right, list): ids2 = [right] else: ids2 = right @@ -290,22 +514,16 @@ class expression(object): if operator in ['like','ilike','in','=']: #no result found with given search criteria call_null = False - self.__exp[i] = ('id','=',0) - else: - call_null = True - operator = 'in' # operator changed because ids are directly related to main object + self.__exp[i] = FALSE_LEAF else: - call_null = False - o2m_op = 'in' - if operator in ['not like','not ilike','not in','<>','!=']: - o2m_op = 'not in' - self.__exp[i] = ('id', o2m_op, self.__execute_recursive_in(cr, field._fields_id, field_obj._table, 'id', ids2, operator, field._type)) + ids2 = select_from_where(cr, field._fields_id, field_obj._table, 'id', ids2, operator) + if ids2: + call_null = False + self.__exp[i] = ('id', 'in', ids2) if call_null: - o2m_op = 'not in' - if operator in ['not like','not ilike','not in','<>','!=']: - o2m_op = 'in' - self.__exp[i] = ('id', o2m_op, self.__execute_recursive_in(cr, field._fields_id, field_obj._table, 'id', [], operator, field._type) or [0]) + o2m_op = 'in' if operator in NEGATIVE_TERM_OPERATORS else 'not in' + self.__exp[i] = ('id', o2m_op, select_distinct_from_where_not_null(cr, field._fields_id, field_obj._table)) elif field._type == 'many2many': #FIXME @@ -313,10 +531,10 @@ class expression(object): def _rec_convert(ids): if field_obj == table: return ids - return self.__execute_recursive_in(cr, field._id1, field._rel, field._id2, ids, operator, field._type) + return select_from_where(cr, field._id1, field._rel, field._id2, ids, operator) - ids2 = child_of_right_to_ids(right) - dom = _rec_get(ids2, field_obj) + ids2 = to_ids(right, field_obj) + dom = child_of_domain('id', ids2, field_obj) ids2 = field_obj.search(cr, uid, dom, context=context) self.__exp[i] = ('id', 'in', _rec_convert(ids2)) else: @@ -335,34 +553,28 @@ class expression(object): if operator in ['like','ilike','in','=']: #no result found with given search criteria call_null_m2m = False - self.__exp[i] = ('id','=',0) + self.__exp[i] = FALSE_LEAF else: - call_null_m2m = True operator = 'in' # operator changed because ids are directly related to main object else: call_null_m2m = False - m2m_op = 'in' - if operator in ['not like','not ilike','not in','<>','!=']: - m2m_op = 'not in' + m2m_op = 'not in' if operator in NEGATIVE_TERM_OPERATORS else 'in' + self.__exp[i] = ('id', m2m_op, select_from_where(cr, field._id1, field._rel, field._id2, res_ids, operator) or [0]) - self.__exp[i] = ('id', m2m_op, self.__execute_recursive_in(cr, field._id1, field._rel, field._id2, res_ids, operator, field._type) or [0]) if call_null_m2m: - m2m_op = 'not in' - if operator in ['not like','not ilike','not in','<>','!=']: - m2m_op = 'in' - self.__exp[i] = ('id', m2m_op, self.__execute_recursive_in(cr, field._id1, field._rel, field._id2, [], operator, field._type) or [0]) + m2m_op = 'in' if operator in NEGATIVE_TERM_OPERATORS else 'not in' + self.__exp[i] = ('id', m2m_op, select_distinct_from_where_not_null(cr, field._id1, field._rel)) elif field._type == 'many2one': if operator == 'child_of': - ids2 = child_of_right_to_ids(right) - self.__operator = 'in' + ids2 = to_ids(right, field_obj) if field._obj != working_table._name: - dom = _rec_get(ids2, field_obj, left=left, prefix=field._obj) + dom = child_of_domain(left, ids2, field_obj, prefix=field._obj) else: - dom = _rec_get(ids2, working_table, parent=left) + dom = child_of_domain('id', ids2, working_table, parent=left) self.__exp = self.__exp[:i] + dom + self.__exp[i+1:] else: - def _get_expression(field_obj,cr, uid, left, right, operator, context=None): + def _get_expression(field_obj, cr, uid, left, right, operator, context=None): if context is None: context = {} c = context.copy() @@ -370,46 +582,35 @@ class expression(object): #Special treatment to ill-formed domains operator = ( operator in ['<','>','<=','>='] ) and 'in' or operator - dict_op = {'not in':'!=','in':'=','=':'in','!=':'not in','<>':'not in'} - if isinstance(right,tuple): + dict_op = {'not in':'!=','in':'=','=':'in','!=':'not in'} + if isinstance(right, tuple): right = list(right) - if (not isinstance(right,list)) and operator in ['not in','in']: + if (not isinstance(right, list)) and operator in ['not in','in']: operator = dict_op[operator] - elif isinstance(right,list) and operator in ['<>','!=','=']: #for domain (FIELD,'=',['value1','value2']) + elif isinstance(right, list) and operator in ['!=','=']: #for domain (FIELD,'=',['value1','value2']) operator = dict_op[operator] - res_ids = field_obj.name_search(cr, uid, right, [], operator, limit=None, context=c) - if not res_ids: - return ('id','=',0) - else: - right = map(lambda x: x[0], res_ids) - return (left, 'in', right) + res_ids = [x[0] for x in field_obj.name_search(cr, uid, right, [], operator, limit=None, context=c)] + if operator in NEGATIVE_TERM_OPERATORS: + res_ids.append(False) # TODO this should not be appended if False was in 'right' + return (left, 'in', res_ids) m2o_str = False if right: if isinstance(right, basestring): # and not isinstance(field, fields.related): m2o_str = True - elif isinstance(right,(list,tuple)): + elif isinstance(right, (list, tuple)): m2o_str = True for ele in right: if not isinstance(ele, basestring): m2o_str = False break + if m2o_str: + self.__exp[i] = _get_expression(field_obj, cr, uid, left, right, operator, context=context) elif right == []: - m2o_str = False - if operator in ('not in', '!=', '<>'): - # (many2one not in []) should return all records - self.__exp[i] = self.__DUMMY_LEAF - else: - self.__exp[i] = ('id','=',0) - else: - new_op = '=' - if operator in ['not like','not ilike','not in','<>','!=']: - new_op = '!=' - #Is it ok to put 'left' and not 'id' ? - self.__exp[i] = (left,new_op,False) + pass # Handled by __leaf_to_sql(). + else: # right is False + pass # Handled by __leaf_to_sql(). - if m2o_str: - self.__exp[i] = _get_expression(field_obj,cr, uid, left, right, operator, context=context) else: # other field type # add the time part to datetime field when it's not there: @@ -425,127 +626,160 @@ class expression(object): self.__exp[i] = tuple(self.__exp[i]) if field.translate: - if operator in ('like', 'ilike', 'not like', 'not ilike'): + need_wildcard = operator in ('like', 'ilike', 'not like', 'not ilike') + sql_operator = {'=like':'like','=ilike':'ilike'}.get(operator,operator) + if need_wildcard: right = '%%%s%%' % right - operator = operator == '=like' and 'like' or operator - - query1 = '( SELECT res_id' \ + subselect = '( SELECT res_id' \ ' FROM ir_translation' \ ' WHERE name = %s' \ ' AND lang = %s' \ ' AND type = %s' instr = ' %s' #Covering in,not in operators with operands (%s,%s) ,etc. - if operator in ['in','not in']: + if sql_operator in ['in','not in']: instr = ','.join(['%s'] * len(right)) - query1 += ' AND value ' + operator + ' ' +" (" + instr + ")" \ + subselect += ' AND value ' + sql_operator + ' ' +" (" + instr + ")" \ ') UNION (' \ ' SELECT id' \ ' FROM "' + working_table._table + '"' \ - ' WHERE "' + left + '" ' + operator + ' ' +" (" + instr + "))" + ' WHERE "' + left + '" ' + sql_operator + ' ' +" (" + instr + "))" else: - query1 += ' AND value ' + operator + instr + \ + subselect += ' AND value ' + sql_operator + instr + \ ') UNION (' \ ' SELECT id' \ ' FROM "' + working_table._table + '"' \ - ' WHERE "' + left + '" ' + operator + instr + ")" + ' WHERE "' + left + '" ' + sql_operator + instr + ")" - query2 = [working_table._name + ',' + left, + params = [working_table._name + ',' + left, context.get('lang', False) or 'en_US', 'model', right, right, ] - self.__exp[i] = ('id', 'inselect', (query1, query2)) - return self + self.__exp[i] = ('id', 'inselect', (subselect, params)) def __leaf_to_sql(self, leaf, table): - if leaf == self.__DUMMY_LEAF: - return ('(1=1)', []) left, operator, right = leaf - if operator == 'inselect': - query = '(%s.%s in (%s))' % (table._table, left, right[0]) - params = right[1] - elif operator in ['in', 'not in']: - params = right and right[:] or [] - len_before = len(params) - for i in range(len_before)[::-1]: - if params[i] == False: - del params[i] + # final sanity checks - should never fail + assert operator in (TERM_OPERATORS + ('inselect',)), \ + "Invalid operator %r in domain term %r" % (operator, leaf) + assert leaf in (TRUE_LEAF, FALSE_LEAF) or left in table._all_columns \ + or left in MAGIC_COLUMNS, "Invalid field %r in domain term %r" % (left, leaf) - len_after = len(params) - check_nulls = len_after != len_before - query = '(1=0)' - - if len_after: - if left == 'id': - instr = ','.join(['%s'] * len_after) - else: - instr = ','.join([table._columns[left]._symbol_set[0]] * len_after) - query = '(%s.%s %s (%s))' % (table._table, left, operator, instr) - else: - # the case for [field, 'in', []] or [left, 'not in', []] - if operator == 'in': - query = '(%s.%s IS NULL)' % (table._table, left) - else: - query = '(%s.%s IS NOT NULL)' % (table._table, left) - if check_nulls: - query = '(%s OR %s.%s IS NULL)' % (query, table._table, left) - else: + if leaf == TRUE_LEAF: + query = 'TRUE' params = [] - if right == False and (leaf[0] in table._columns) and table._columns[leaf[0]]._type=="boolean" and (operator == '='): - query = '(%s.%s IS NULL or %s.%s = false )' % (table._table, left,table._table, left) - elif (((right == False) and (type(right)==bool)) or (right is None)) and (operator == '='): - query = '%s.%s IS NULL ' % (table._table, left) - elif right == False and (leaf[0] in table._columns) and table._columns[leaf[0]]._type=="boolean" and (operator in ['<>', '!=']): - query = '(%s.%s IS NOT NULL and %s.%s != false)' % (table._table, left,table._table, left) - elif (((right == False) and (type(right)==bool)) or right is None) and (operator in ['<>', '!=']): - query = '%s.%s IS NOT NULL' % (table._table, left) - elif (operator == '=?'): - op = '=' - if (right is False or right is None): - return ( 'TRUE',[]) - if left in table._columns: - format = table._columns[left]._symbol_set[0] - query = '(%s.%s %s %s)' % (table._table, left, op, format) - params = table._columns[left]._symbol_set[1](right) - else: - query = "(%s.%s %s '%%s')" % (table._table, left, op) - params = right + elif leaf == FALSE_LEAF: + query = 'FALSE' + params = [] - else: - if left == 'id': - query = '%s.id %s %%s' % (table._table, operator) - params = right - else: - like = operator in ('like', 'ilike', 'not like', 'not ilike') + elif operator == 'inselect': + query = '(%s."%s" in (%s))' % (table._table, left, right[0]) + params = right[1] - op = {'=like':'like','=ilike':'ilike'}.get(operator,operator) - if left in table._columns: - format = like and '%s' or table._columns[left]._symbol_set[0] - query = '(%s.%s %s %s)' % (table._table, left, op, format) + elif operator in ['in', 'not in']: + # Two cases: right is a boolean or a list. The boolean case is an + # abuse and handled for backward compatibility. + if isinstance(right, bool): + _logger.warning("The domain term '%s' should use the '=' or '!=' operator." % (leaf,)) + if operator == 'in': + r = 'NOT NULL' if right else 'NULL' + else: + r = 'NULL' if right else 'NOT NULL' + query = '(%s."%s" IS %s)' % (table._table, left, r) + params = [] + elif isinstance(right, (list, tuple)): + params = right[:] + check_nulls = False + for i in range(len(params))[::-1]: + if params[i] == False: + check_nulls = True + del params[i] + + if params: + if left == 'id': + instr = ','.join(['%s'] * len(params)) else: - query = "(%s.%s %s '%s')" % (table._table, left, op, right) + instr = ','.join([table._columns[left]._symbol_set[0]] * len(params)) + query = '(%s."%s" %s (%s))' % (table._table, left, operator, instr) + else: + # The case for (left, 'in', []) or (left, 'not in', []). + query = 'FALSE' if operator == 'in' else 'TRUE' - add_null = False - if like: - if isinstance(right, str): - str_utf8 = right - elif isinstance(right, unicode): - str_utf8 = right.encode('utf-8') - else: - str_utf8 = str(right) - params = '%%%s%%' % str_utf8 - add_null = not str_utf8 - elif left in table._columns: - params = table._columns[left]._symbol_set[1](right) + if check_nulls and operator == 'in': + query = '(%s OR %s."%s" IS NULL)' % (query, table._table, left) + elif not check_nulls and operator == 'not in': + query = '(%s OR %s."%s" IS NULL)' % (query, table._table, left) + elif check_nulls and operator == 'not in': + query = '(%s AND %s."%s" IS NOT NULL)' % (query, table._table, left) # needed only for TRUE. + else: # Must not happen + raise ValueError("Invalid domain term %r" % (leaf,)) - if add_null: - query = '(%s OR %s IS NULL)' % (query, left) + elif right == False and (left in table._columns) and table._columns[left]._type=="boolean" and (operator == '='): + query = '(%s."%s" IS NULL or %s."%s" = false )' % (table._table, left, table._table, left) + params = [] + + elif (right is False or right is None) and (operator == '='): + query = '%s."%s" IS NULL ' % (table._table, left) + params = [] + + elif right == False and (left in table._columns) and table._columns[left]._type=="boolean" and (operator == '!='): + query = '(%s."%s" IS NOT NULL and %s."%s" != false)' % (table._table, left, table._table, left) + params = [] + + elif (right is False or right is None) and (operator == '!='): + query = '%s."%s" IS NOT NULL' % (table._table, left) + params = [] + + elif (operator == '=?'): + if (right is False or right is None): + # '=?' is a short-circuit that makes the term TRUE if right is None or False + query = 'TRUE' + params = [] + else: + # '=?' behaves like '=' in other cases + query, params = self.__leaf_to_sql((left, '=', right), table) + + elif left == 'id': + query = '%s.id %s %%s' % (table._table, operator) + params = right + + else: + need_wildcard = operator in ('like', 'ilike', 'not like', 'not ilike') + sql_operator = {'=like':'like','=ilike':'ilike'}.get(operator,operator) + + if left in table._columns: + format = need_wildcard and '%s' or table._columns[left]._symbol_set[0] + if self.has_unaccent and sql_operator in ('ilike', 'not ilike'): + query = '(unaccent(%s."%s") %s unaccent(%s))' % (table._table, left, sql_operator, format) + else: + query = '(%s."%s" %s %s)' % (table._table, left, sql_operator, format) + elif left in MAGIC_COLUMNS: + query = "(%s.\"%s\" %s %%s)" % (table._table, left, sql_operator) + params = right + else: # Must not happen + raise ValueError("Invalid field %r in domain term %r" % (left, leaf)) + + add_null = False + if need_wildcard: + if isinstance(right, str): + str_utf8 = right + elif isinstance(right, unicode): + str_utf8 = right.encode('utf-8') + else: + str_utf8 = str(right) + params = '%%%s%%' % str_utf8 + add_null = not str_utf8 + elif left in table._columns: + params = table._columns[left]._symbol_set[1](right) + + if add_null: + query = '(%s OR %s."%s" IS NULL)' % (query, table._table, left) if isinstance(params, basestring): params = [params] @@ -555,25 +789,26 @@ class expression(object): def to_sql(self): stack = [] params = [] + # Process the domain from right to left, using a stack, to generate a SQL expression. for i, e in reverse_enumerate(self.__exp): - if self._is_leaf(e, internal=True): + if is_leaf(e, internal=True): table = self.__field_tables.get(i, self.__main_table) q, p = self.__leaf_to_sql(e, table) params.insert(0, p) stack.append(q) + elif e == NOT_OPERATOR: + stack.append('(NOT (%s))' % (stack.pop(),)) else: - if e == NOT_OPERATOR: - stack.append('(NOT (%s))' % (stack.pop(),)) - else: - ops = {AND_OPERATOR: ' AND ', OR_OPERATOR: ' OR '} - q1 = stack.pop() - q2 = stack.pop() - stack.append('(%s %s %s)' % (q1, ops[e], q2,)) + ops = {AND_OPERATOR: ' AND ', OR_OPERATOR: ' OR '} + q1 = stack.pop() + q2 = stack.pop() + stack.append('(%s %s %s)' % (q1, ops[e], q2,)) - query = ' AND '.join(reversed(stack)) + assert len(stack) == 1 + query = stack[0] joins = ' AND '.join(self.__joins) if joins: - query = '(%s) AND (%s)' % (joins, query) + query = '(%s) AND %s' % (joins, query) return (query, flatten(params)) def get_tables(self): diff --git a/openerp/osv/fields.py b/openerp/osv/fields.py index 7a8f460f5cb..6619e66b075 100644 --- a/openerp/osv/fields.py +++ b/openerp/osv/fields.py @@ -55,7 +55,7 @@ def _symbol_set(symb): class _column(object): """ Base of all fields, a database column - + An instance of this object is a *description* of a database column. It will not hold any data, but only provide the methods to manipulate data of an ORM record or even prepare/update the database to hold such a field of data. @@ -72,7 +72,7 @@ class _column(object): _symbol_set = (_symbol_c, _symbol_f) _symbol_get = None - def __init__(self, string='unknown', required=False, readonly=False, domain=None, context=None, states=None, priority=0, change_default=False, size=None, ondelete="set null", translate=False, select=False, manual=False, **args): + def __init__(self, string='unknown', required=False, readonly=False, domain=None, context=None, states=None, priority=0, change_default=False, size=None, ondelete=None, translate=False, select=False, manual=False, **args): """ The 'manual' keyword argument specifies if the field is a custom one. @@ -91,7 +91,7 @@ class _column(object): self.help = args.get('help', '') self.priority = priority self.change_default = change_default - self.ondelete = ondelete + self.ondelete = ondelete.lower() if ondelete else None # defaults to 'set null' in ORM self.translate = translate self._domain = domain self._context = context @@ -112,12 +112,6 @@ class _column(object): def set(self, cr, obj, id, name, value, user=None, context=None): cr.execute('update '+obj._table+' set '+name+'='+self._symbol_set[0]+' where id=%s', (self._symbol_set[1](value), id)) - def set_memory(self, cr, obj, id, name, value, user=None, context=None): - raise Exception(_('Not implemented set_memory method !')) - - def get_memory(self, cr, obj, ids, name, user=None, context=None, values=None): - raise Exception(_('Not implemented get_memory method !')) - def get(self, cr, obj, ids, name, user=None, offset=0, context=None, values=None): raise Exception(_('undefined get method !')) @@ -126,9 +120,6 @@ class _column(object): res = obj.read(cr, uid, ids, [name], context=context) return [x[name] for x in res] - def search_memory(self, cr, obj, args, name, value, offset=0, limit=None, uid=None, context=None): - raise Exception(_('Not implemented search_memory method !')) - # --------------------------------------------------------- # Simple fields @@ -269,7 +260,7 @@ class binary(_column): _column.__init__(self, string=string, **args) self.filters = filters - def get_memory(self, cr, obj, ids, name, user=None, context=None, values=None): + def get(self, cr, obj, ids, name, user=None, context=None, values=None): if not context: context = {} if not values: @@ -293,9 +284,6 @@ class binary(_column): res[i] = val return res - get = get_memory - - class selection(_column): _type = 'selection' @@ -355,30 +343,6 @@ class many2one(_column): _column.__init__(self, string=string, **args) self._obj = obj - def set_memory(self, cr, obj, id, field, values, user=None, context=None): - obj.datas.setdefault(id, {}) - obj.datas[id][field] = values - - def get_memory(self, cr, obj, ids, name, user=None, context=None, values=None): - result = {} - for id in ids: - result[id] = obj.datas[id].get(name, False) - - # build a dictionary of the form {'id_of_distant_resource': name_of_distant_resource} - # we use uid=1 because the visibility of a many2one field value (just id and name) - # must be the access right of the parent form and not the linked object itself. - obj = obj.pool.get(self._obj) - records = dict(obj.name_get(cr, 1, - list(set([x for x in result.values() if x and isinstance(x, (int,long))])), - context=context)) - for id in ids: - if result[id] in records: - result[id] = (result[id], records[result[id]]) - else: - result[id] = False - - return result - def get(self, cr, obj, ids, name, user=None, context=None, values=None): if context is None: context = {} @@ -447,55 +411,6 @@ class one2many(_column): #one2many can't be used as condition for defaults assert(self.change_default != True) - def get_memory(self, cr, obj, ids, name, user=None, offset=0, context=None, values=None): - if context is None: - context = {} - if self._context: - context = context.copy() - context.update(self._context) - if not values: - values = {} - res = {} - for id in ids: - res[id] = [] - ids2 = obj.pool.get(self._obj).search(cr, user, [(self._fields_id, 'in', ids)], limit=self._limit, context=context) - for r in obj.pool.get(self._obj).read(cr, user, ids2, [self._fields_id], context=context, load='_classic_write'): - if r[self._fields_id] in res: - res[r[self._fields_id]].append(r['id']) - return res - - def set_memory(self, cr, obj, id, field, values, user=None, context=None): - if not context: - context = {} - if self._context: - context = context.copy() - context.update(self._context) - if not values: - return - obj = obj.pool.get(self._obj) - for act in values: - if act[0] == 0: - act[2][self._fields_id] = id - obj.create(cr, user, act[2], context=context) - elif act[0] == 1: - obj.write(cr, user, [act[1]], act[2], context=context) - elif act[0] == 2: - obj.unlink(cr, user, [act[1]], context=context) - elif act[0] == 3: - obj.datas[act[1]][self._fields_id] = False - elif act[0] == 4: - obj.datas[act[1]][self._fields_id] = id - elif act[0] == 5: - for o in obj.datas.values(): - if o[self._fields_id] == id: - o[self._fields_id] = False - elif act[0] == 6: - for id2 in (act[2] or []): - obj.datas[id2][self._fields_id] = id - - def search_memory(self, cr, obj, args, name, value, offset=0, limit=None, uid=None, operator='like', context=None): - raise _('Not Implemented') - def get(self, cr, obj, ids, name, user=None, offset=0, context=None, values=None): if context is None: context = {} @@ -578,14 +493,34 @@ class one2many(_column): # (6, ?, ids) set a list of links # class many2many(_column): + """Encapsulates the logic of a many-to-many bidirectional relationship, handling the + low-level details of the intermediary relationship table transparently. + + :param str obj: destination model + :param str rel: optional name of the intermediary relationship table. If not specified, + a canonical name will be derived based on the alphabetically-ordered + model names of the source and destination (in the form: ``amodel_bmodel_rel``). + Automatic naming is not possible when the source and destination are + the same, for obvious ambiguity reasons. + :param str id1: optional name for the column holding the foreign key to the current + model in the relationship table. If not specified, a canonical name + will be derived based on the model name (in the form: `src_model_id`). + :param str id2: optional name for the column holding the foreign key to the destination + model in the relationship table. If not specified, a canonical name + will be derived based on the model name (in the form: `dest_model_id`) + :param str string: field label + """ _classic_read = False _classic_write = False _prefetch = False _type = 'many2many' - def __init__(self, obj, rel, id1, id2, string='unknown', limit=None, **args): + + def __init__(self, obj, rel=None, id1=None, id2=None, string='unknown', limit=None, **args): + """ + """ _column.__init__(self, string=string, **args) self._obj = obj - if '.' in rel: + if rel and '.' in rel: raise Exception(_('The second argument of the many2many field %s must be a SQL table !'\ 'You used %s, which is not a valid SQL table name.')% (string,rel)) self._rel = rel @@ -593,7 +528,30 @@ class many2many(_column): self._id2 = id2 self._limit = limit - def get(self, cr, obj, ids, name, user=None, offset=0, context=None, values=None): + def _sql_names(self, source_model): + """Return the SQL names defining the structure of the m2m relationship table + + :return: (m2m_table, local_col, dest_col) where m2m_table is the table name, + local_col is the name of the column holding the current model's FK, and + dest_col is the name of the column holding the destination model's FK, and + """ + tbl, col1, col2 = self._rel, self._id1, self._id2 + if not all((tbl, col1, col2)): + # the default table name is based on the stable alphabetical order of tables + dest_model = source_model.pool.get(self._obj) + tables = tuple(sorted([source_model._table, dest_model._table])) + if not tbl: + assert tables[0] != tables[1], 'Implicit/Canonical naming of m2m relationship table '\ + 'is not possible when source and destination models are '\ + 'the same' + tbl = '%s_%s_rel' % tables + if not col1: + col1 = '%s_id' % source_model._table + if not col2: + col2 = '%s_id' % dest_model._table + return (tbl, col1, col2) + + def get(self, cr, model, ids, name, user=None, offset=0, context=None, values=None): if not context: context = {} if not values: @@ -606,7 +564,8 @@ class many2many(_column): if offset: warnings.warn("Specifying offset at a many2many.get() may produce unpredictable results.", DeprecationWarning, stacklevel=2) - obj = obj.pool.get(self._obj) + obj = model.pool.get(self._obj) + rel, id1, id2 = self._sql_names(model) # static domains are lists, and are evaluated both here and on client-side, while string # domains supposed by dynamic and evaluated on client-side only (thus ignored here) @@ -636,11 +595,11 @@ class many2many(_column): %(order_by)s \ %(limit)s \ OFFSET %(offset)d' \ - % {'rel': self._rel, + % {'rel': rel, 'from_c': from_c, 'tbl': obj._table, - 'id1': self._id1, - 'id2': self._id2, + 'id1': id1, + 'id2': id2, 'where_c': where_c, 'limit': limit_str, 'order_by': order_by, @@ -651,31 +610,32 @@ class many2many(_column): res[r[1]].append(r[0]) return res - def set(self, cr, obj, id, name, values, user=None, context=None): + def set(self, cr, model, id, name, values, user=None, context=None): if not context: context = {} if not values: return - obj = obj.pool.get(self._obj) + rel, id1, id2 = self._sql_names(model) + obj = model.pool.get(self._obj) for act in values: if not (isinstance(act, list) or isinstance(act, tuple)) or not act: continue if act[0] == 0: idnew = obj.create(cr, user, act[2], context=context) - cr.execute('insert into '+self._rel+' ('+self._id1+','+self._id2+') values (%s,%s)', (id, idnew)) + cr.execute('insert into '+rel+' ('+id1+','+id2+') values (%s,%s)', (id, idnew)) elif act[0] == 1: obj.write(cr, user, [act[1]], act[2], context=context) elif act[0] == 2: obj.unlink(cr, user, [act[1]], context=context) elif act[0] == 3: - cr.execute('delete from '+self._rel+' where ' + self._id1 + '=%s and '+ self._id2 + '=%s', (id, act[1])) + cr.execute('delete from '+rel+' where ' + id1 + '=%s and '+ id2 + '=%s', (id, act[1])) elif act[0] == 4: # following queries are in the same transaction - so should be relatively safe - cr.execute('SELECT 1 FROM '+self._rel+' WHERE '+self._id1+' = %s and '+self._id2+' = %s', (id, act[1])) + cr.execute('SELECT 1 FROM '+rel+' WHERE '+id1+' = %s and '+id2+' = %s', (id, act[1])) if not cr.fetchone(): - cr.execute('insert into '+self._rel+' ('+self._id1+','+self._id2+') values (%s,%s)', (id, act[1])) + cr.execute('insert into '+rel+' ('+id1+','+id2+') values (%s,%s)', (id, act[1])) elif act[0] == 5: - cr.execute('update '+self._rel+' set '+self._id2+'=null where '+self._id2+'=%s', (id,)) + cr.execute('delete from '+rel+' where ' + id1 + ' = %s', (id,)) elif act[0] == 6: d1, d2,tables = obj.pool.get('ir.rule').domain_get(cr, user, obj._name, context=context) @@ -683,10 +643,10 @@ class many2many(_column): d1 = ' and ' + ' and '.join(d1) else: d1 = '' - cr.execute('delete from '+self._rel+' where '+self._id1+'=%s AND '+self._id2+' IN (SELECT '+self._rel+'.'+self._id2+' FROM '+self._rel+', '+','.join(tables)+' WHERE '+self._rel+'.'+self._id1+'=%s AND '+self._rel+'.'+self._id2+' = '+obj._table+'.id '+ d1 +')', [id, id]+d2) + cr.execute('delete from '+rel+' where '+id1+'=%s AND '+id2+' IN (SELECT '+rel+'.'+id2+' FROM '+rel+', '+','.join(tables)+' WHERE '+rel+'.'+id1+'=%s AND '+rel+'.'+id2+' = '+obj._table+'.id '+ d1 +')', [id, id]+d2) for act_nbr in act[2]: - cr.execute('insert into '+self._rel+' ('+self._id1+','+self._id2+') values (%s, %s)', (id, act_nbr)) + cr.execute('insert into '+rel+' ('+id1+','+id2+') values (%s, %s)', (id, act_nbr)) # # TODO: use a name_search @@ -694,32 +654,6 @@ class many2many(_column): def search(self, cr, obj, args, name, value, offset=0, limit=None, uid=None, operator='like', context=None): return obj.pool.get(self._obj).search(cr, uid, args+self._domain+[('name', operator, value)], offset, limit, context=context) - def get_memory(self, cr, obj, ids, name, user=None, offset=0, context=None, values=None): - result = {} - for id in ids: - result[id] = obj.datas[id].get(name, []) - return result - - def set_memory(self, cr, obj, id, name, values, user=None, context=None): - if not values: - return - for act in values: - # TODO: use constants instead of these magic numbers - if act[0] == 0: - raise _('Not Implemented') - elif act[0] == 1: - raise _('Not Implemented') - elif act[0] == 2: - raise _('Not Implemented') - elif act[0] == 3: - raise _('Not Implemented') - elif act[0] == 4: - raise _('Not Implemented') - elif act[0] == 5: - raise _('Not Implemented') - elif act[0] == 6: - obj.datas[id][name] = act[2] - def get_nice_size(value): size = 0 @@ -801,8 +735,8 @@ class function(_column): Implements the function field. - :param orm_template model: model to which the field belongs (should be ``self`` for - a model method) + :param orm model: model to which the field belongs (should be ``self`` for + a model method) :param field_name(s): name of the field to compute, or if ``multi`` is provided, list of field names to compute. :type field_name(s): str | [str] @@ -865,8 +799,8 @@ class function(_column): Callable that implements the ``write`` operation for the function field. - :param orm_template model: model to which the field belongs (should be ``self`` for - a model method) + :param orm model: model to which the field belongs (should be ``self`` for + a model method) :param int id: the identifier of the object to write on :param str field_name: name of the field to set :param fnct_inv_arg: arbitrary value passed when declaring the function field @@ -887,10 +821,10 @@ class function(_column): a search criterion based on the function field into a new domain based only on columns that are stored in the database. - :param orm_template model: model to which the field belongs (should be ``self`` for - a model method) - :param orm_template model_again: same value as ``model`` (seriously! this is for backwards - compatibility) + :param orm model: model to which the field belongs (should be ``self`` for + a model method) + :param orm model_again: same value as ``model`` (seriously! this is for backwards + compatibility) :param str field_name: name of the field to search on :param list criterion: domain component specifying the search criterion on the field. :rtype: list @@ -935,7 +869,7 @@ class function(_column): corresponding records in the source model (whose field values need to be recomputed). - :param orm_template model: trigger_model + :param orm model: trigger_model :param list trigger_ids: ids of the records of trigger_model that were modified :rtype: list @@ -1064,14 +998,11 @@ class function(_column): result[id] = self.postprocess(cr, uid, obj, name, result[id], context) return result - get_memory = get - def set(self, cr, obj, id, name, value, user=None, context=None): if not context: context = {} if self._fnct_inv: self._fnct_inv(obj, cr, user, id, name, value, self._fnct_inv_arg, context) - set_memory = set # --------------------------------------------------------- # Related fields @@ -1295,7 +1226,7 @@ class property(function): def _fnct_read(self, obj, cr, uid, ids, prop_names, obj_dest, context=None): prop = obj.pool.get('ir.property') - # get the default values (for res_id = False) for the property fields + # get the default values (for res_id = False) for the property fields default_val = self._get_defaults(obj, cr, uid, prop_names, context) # build the dictionary that will be returned @@ -1417,12 +1348,16 @@ class column_info(object): :attr parent_column: the name of the column containing the m2o relationship to the parent model that contains this column, None for local columns. + :attr original_parent: if the column is inherited, name of the original + parent model that contains it i.e in case of multilevel + inheritence, None for local columns. """ - def __init__(self, name, column, parent_model=None, parent_column=None): + def __init__(self, name, column, parent_model=None, parent_column=None, original_parent=None): self.name = name self.column = column self.parent_model = parent_model self.parent_column = parent_column + self.original_parent = original_parent # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index 7efe2272754..6d205feeb43 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -38,31 +38,32 @@ - classicals (varchar, integer, boolean, ...) - relations (one2many, many2one, many2many) - functions - + """ import calendar import copy import datetime import logging -import warnings import operator import pickle import re +import simplejson import time import traceback import types -import simplejson - -import openerp.netsvc as netsvc +import warnings from lxml import etree -from openerp.tools.config import config -from openerp.tools.translate import _ import fields -from query import Query +import openerp +import openerp.netsvc as netsvc import openerp.tools as tools +from openerp.tools.config import config from openerp.tools.safe_eval import safe_eval as eval +from openerp.tools.translate import _ +from openerp import SUPERUSER_ID +from query import Query # List of etree._Element subclasses that we choose to ignore when parsing XML. from openerp.tools import SKIPPED_ELEMENT_TYPES @@ -70,9 +71,6 @@ from openerp.tools import SKIPPED_ELEMENT_TYPES regex_order = re.compile('^(([a-z0-9_]+|"[a-z0-9_]+")( *desc| *asc)?( *, *|))+$', re.I) regex_object_name = re.compile(r'^[a-z0-9_.]+$') -# Super-user identifier (aka Administrator aka root) -ROOT_USER_ID = 1 - def transfer_field_to_modifiers(field, modifiers): default_values = {} state_exceptions = {} @@ -165,7 +163,7 @@ def modifiers_tests(): test_modifiers({}, '{}') test_modifiers({"invisible": True}, '{"invisible": true}') test_modifiers({"invisible": False}, '{}') - + def check_object_name(name): """ Check if the given name is a valid openerp object name. @@ -212,6 +210,19 @@ def last_day_of_current_month(): def intersect(la, lb): return filter(lambda x: x in lb, la) +def fix_import_export_id_paths(fieldname): + """ + Fixes the id fields in import and exports, and splits field paths + on '/'. + + :param str fieldname: name of the field to import/export + :return: split field name + :rtype: list of str + """ + fixed_db_id = re.sub(r'([^/])\.id', r'\1/.id', fieldname) + fixed_external_id = re.sub(r'([^/]):id', r'\1/id', fixed_db_id) + return fixed_external_id.split('/') + class except_orm(Exception): def __init__(self, name, value): self.name = name @@ -252,7 +263,7 @@ class browse_null(object): # class browse_record_list(list): """ Collection of browse objects - + Such an instance will be returned when doing a ``browse([ids..])`` and will be iterable, yielding browse() objects """ @@ -267,9 +278,9 @@ class browse_record_list(list): class browse_record(object): """ An object that behaves like a row of an object's table. It has attributes after the columns of the corresponding object. - + Examples:: - + uobj = pool.get('res.users') user_rec = uobj.browse(cr, uid, 104) name = user_rec.name @@ -572,22 +583,36 @@ class MetaModel(type): self.module_to_models.setdefault(self._module, []).append(self) -class orm_template(object): +# Definition of log access columns, automatically added to models if +# self._log_access is True +LOG_ACCESS_COLUMNS = { + 'create_uid': 'INTEGER REFERENCES res_users ON DELETE SET NULL', + 'create_date': 'TIMESTAMP', + 'write_uid': 'INTEGER REFERENCES res_users ON DELETE SET NULL', + 'write_date': 'TIMESTAMP' +} +# special columns automatically created by the ORM +MAGIC_COLUMNS = ['id'] + LOG_ACCESS_COLUMNS.keys() + +class BaseModel(object): """ Base class for OpenERP models. - OpenERP models are created by inheriting from this class (although - not directly; more specifically by inheriting from osv or - osv_memory). The constructor is called once, usually directly - after the class definition, e.g.: + OpenERP models are created by inheriting from this class' subclasses: - class user(osv): - ... - user() + * Model: for regular database-persisted models + * TransientModel: for temporary data, stored in the database but automatically + vaccuumed every so often + * AbstractModel: for abstract super classes meant to be shared by multiple + _inheriting classes (usually Models or TransientModels) - The system will later instanciate the class once per database (on + The system will later instantiate the class once per database (on which the class' module is installed). + To create a class that should not be instantiated, the _register class attribute + may be set to False. """ + __metaclass__ = MetaModel + _register = False # Set to false if the model shouldn't be automatically discovered. _name = None _columns = {} _constraints = [] @@ -600,22 +625,42 @@ class orm_template(object): _order = 'id' _sequence = None _description = None + + # Transience + _transient = False # True in a TransientModel + _transient_max_count = None + _transient_max_hours = None + _transient_check_time = 20 + + # structure: + # { 'parent_model': 'm2o_field', ... } _inherits = {} - # Mapping from inherits'd field name to triple (m, r, f) - # where m is the model from which it is inherits'd, - # r is the (local) field towards m, - # and f is the _column object itself. + + # Mapping from inherits'd field name to triple (m, r, f, n) where m is the + # model from which it is inherits'd, r is the (local) field towards m, f + # is the _column object itself, and n is the original (i.e. top-most) + # parent model. + # Example: + # { 'field_name': ('parent_model', 'm2o_field_to_reach_parent', + # field_column_obj, origina_parent_model), ... } _inherit_fields = {} + # Mapping field name/column_info object # This is similar to _inherit_fields but: # 1. includes self fields, # 2. uses column_info instead of a triple. _all_columns = {} + _table = None _invalids = set() _log_create = False + _sql_constraints = [] + _protected = ['read', 'write', 'create', 'default_get', 'perm_read', 'unlink', 'fields_get', 'fields_view_get', 'search', 'name_get', 'distinct_field_get', 'name_search', 'copy', 'import_data', 'search_count', 'exists'] + __logger = logging.getLogger('orm') + __schema = logging.getLogger('orm.schema') CONCURRENCY_CHECK_FIELD = '__last_update' + def log(self, cr, uid, id, message, secondary=False, context=None): if context and context.get('disable_log'): return True @@ -633,9 +678,6 @@ class orm_template(object): """Override this method to do specific things when a view on the object is opened.""" pass - def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, context=None, orderby=False): - raise NotImplementedError(_('The read_group method is not implemented on this object !')) - def _field_create(self, cr, context=None): """ Create entries in ir_model_fields for all the model's fields. @@ -738,19 +780,12 @@ class orm_template(object): break cr.commit() - def _auto_init(self, cr, context=None): - raise_on_invalid_object_name(self._name) - self._field_create(cr, context=context) - - def _auto_end(self, cr, context=None): - pass - # # Goal: try to apply inheritance at the instanciation level and # put objects in the pool var # @classmethod - def makeInstance(cls, pool, cr, attributes): + def create_instance(cls, pool, cr): """ Instanciate a given model. This class method instanciates the class of some model (i.e. a class @@ -765,6 +800,9 @@ class orm_template(object): this method. This is probably unnecessary. """ + attributes = ['_columns', '_defaults', '_inherits', '_constraints', + '_sql_constraints'] + parent_names = getattr(cls, '_inherit', None) if parent_names: if isinstance(parent_names, (str, unicode)): @@ -820,7 +858,10 @@ class orm_template(object): This doesn't create an instance but simply register the model as being part of the module where it is defined. + """ + + # Set the module name (e.g. base, sale, accounting, ...) on the class. module = cls.__module__.split('.')[0] if not hasattr(cls, '_module'): @@ -837,7 +878,15 @@ class orm_template(object): return None def __init__(self, pool, cr): - """ Initialize a model and make it part of the given registry.""" + """ Initialize a model and make it part of the given registry. + + - copy the stored fields' functions in the osv_pool, + - update the _columns with the fields found in ir_model_fields, + - ensure there is a many2one for each _inherits'd parent, + - update the children's _columns, + - give a chance to each field to initialize itself. + + """ pool.add(self._name, self) self.pool = pool @@ -854,26 +903,96 @@ class orm_template(object): if not self._table: self._table = self._name.replace('.', '_') - def browse(self, cr, uid, select, context=None, list_class=None, fields_process=None): - """Fetch records as objects allowing to use dot notation to browse fields and relations + if not hasattr(self, '_log_access'): + # If _log_access is not specified, it is the same value as _auto. + self._log_access = getattr(self, "_auto", True) - :param cr: database cursor - :param user: current user id - :param select: id or list of ids. - :param context: context arguments, like lang, time zone - :rtype: object or list of objects requested + self._columns = self._columns.copy() + for store_field in self._columns: + f = self._columns[store_field] + if hasattr(f, 'digits_change'): + f.digits_change(cr) + if not isinstance(f, fields.function): + continue + if not f.store: + continue + if self._columns[store_field].store is True: + sm = {self._name: (lambda self, cr, uid, ids, c={}: ids, None, 10, None)} + else: + sm = self._columns[store_field].store + for object, aa in sm.items(): + if len(aa) == 4: + (fnct, fields2, order, length) = aa + elif len(aa) == 3: + (fnct, fields2, order) = aa + length = None + else: + raise except_orm('Error', + ('Invalid function definition %s in object %s !\nYou must use the definition: store={object:(fnct, fields, priority, time length)}.' % (store_field, self._name))) + self.pool._store_function.setdefault(object, []) + ok = True + for x, y, z, e, f, l in self.pool._store_function[object]: + if (x==self._name) and (y==store_field) and (e==fields2): + if f == order: + ok = False + if ok: + self.pool._store_function[object].append( (self._name, store_field, fnct, tuple(fields2) if fields2 else None, order, length)) + self.pool._store_function[object].sort(lambda x, y: cmp(x[4], y[4])) - """ - self._list_class = list_class or browse_record_list - cache = {} - # need to accepts ints and longs because ids coming from a method - # launched by button in the interface have a type long... - if isinstance(select, (int, long)): - return browse_record(cr, uid, select, self, cache, context=context, list_class=self._list_class, fields_process=fields_process) - elif isinstance(select, list): - return self._list_class([browse_record(cr, uid, id, self, cache, context=context, list_class=self._list_class, fields_process=fields_process) for id in select], context=context) - else: - return browse_null() + for (key, _, msg) in self._sql_constraints: + self.pool._sql_error[self._table+'_'+key] = msg + + # Load manual fields + + cr.execute("SELECT id FROM ir_model_fields WHERE name=%s AND model=%s", ('state', 'ir.model.fields')) + if cr.fetchone(): + cr.execute('SELECT * FROM ir_model_fields WHERE model=%s AND state=%s', (self._name, 'manual')) + for field in cr.dictfetchall(): + if field['name'] in self._columns: + continue + attrs = { + 'string': field['field_description'], + 'required': bool(field['required']), + 'readonly': bool(field['readonly']), + 'domain': eval(field['domain']) if field['domain'] else None, + 'size': field['size'], + 'ondelete': field['on_delete'], + 'translate': (field['translate']), + 'manual': True, + #'select': int(field['select_level']) + } + + if field['ttype'] == 'selection': + self._columns[field['name']] = fields.selection(eval(field['selection']), **attrs) + elif field['ttype'] == 'reference': + self._columns[field['name']] = fields.reference(selection=eval(field['selection']), **attrs) + elif field['ttype'] == 'many2one': + self._columns[field['name']] = fields.many2one(field['relation'], **attrs) + elif field['ttype'] == 'one2many': + self._columns[field['name']] = fields.one2many(field['relation'], field['relation_field'], **attrs) + elif field['ttype'] == 'many2many': + _rel1 = field['relation'].replace('.', '_') + _rel2 = field['model'].replace('.', '_') + _rel_name = 'x_%s_%s_%s_rel' % (_rel1, _rel2, field['name']) + self._columns[field['name']] = fields.many2many(field['relation'], _rel_name, 'id1', 'id2', **attrs) + else: + self._columns[field['name']] = getattr(fields, field['ttype'])(**attrs) + self._inherits_check() + self._inherits_reload() + if not self._sequence: + self._sequence = self._table + '_id_seq' + for k in self._defaults: + assert (k in self._columns) or (k in self._inherit_fields), 'Default function defined in %s but field %s does not exist !' % (self._name, k,) + for f in self._columns: + self._columns[f].restart() + + # Transience + if self.is_transient(): + self._transient_check_count = 0 + self._transient_max_count = config.get('osv_memory_count_limit') + self._transient_max_hours = config.get('osv_memory_age_limit') + assert self._log_access, "TransientModels must have log_access turned on, "\ + "in order to implement their access rights policy" def __export_row(self, cr, uid, row, fields, context=None): if context is None: @@ -885,7 +1004,7 @@ class orm_template(object): elif field_type == 'integer': return 0 elif field_type == 'boolean': - return False + return 'False' return '' def selection_field(in_field): @@ -918,7 +1037,18 @@ class orm_template(object): else: r = d['name'] else: - break + postfix = 0 + while True: + n = self._table+'_'+str(r['id']) + (postfix and ('_'+str(postfix)) or '' ) + if not model_data.search(cr, uid, [('name', '=', n)]): + break + postfix += 1 + model_data.create(cr, uid, { + 'name': n, + 'model': self._name, + 'res_id': r['id'], + }) + r = n else: r = r[f[i]] # To display external name of selection field when its exported @@ -997,11 +1127,7 @@ class orm_template(object): cols = self._columns.copy() for f in self._inherit_fields: cols.update({f: self._inherit_fields[f][2]}) - def fsplit(fieldname): - fixed_db_id = re.sub(r'([^/])\.id', r'\1/.id', fieldname) - fixed_external_id = re.sub(r'([^/]):id', r'\1/id', fixed_db_id) - return fixed_external_id.split('/') - fields_to_export = map(fsplit, fields_to_export) + fields_to_export = map(fix_import_export_id_paths, fields_to_export) datas = [] for row in self.browse(cr, uid, ids, context): datas += self.__export_row(cr, uid, row, fields_to_export, context) @@ -1011,17 +1137,6 @@ class orm_template(object): """ Import given data in given module - :param cr: database cursor - :param uid: current user id - :param fields: list of fields - :param data: data to import - :param mode: 'init' or 'update' for record creation - :param current_module: module name - :param noupdate: flag for record creation - :param context: context arguments, like lang, time zone, - :param filename: optional file to store partial import state for recovery - :rtype: tuple - This method is used when importing data via client menu. Example of fields to import for a sale.order:: @@ -1034,13 +1149,26 @@ class orm_template(object): order_line/price_unit, order_line/product_uom_qty, order_line/product_uom/id (=xml_id) + + This method returns a 4-tuple with the following structure: + + * The first item is a return code, it returns either ``-1`` in case o + + :param cr: database cursor + :param uid: current user id + :param fields: list of fields + :param data: data to import + :param mode: 'init' or 'update' for record creation + :param current_module: module name + :param noupdate: flag for record creation + :param context: context arguments, like lang, time zone, + :param filename: optional file to store partial import state for recovery + :returns: 4-tuple of a return code, an errored resource, an error message and ??? + :rtype: (int, dict|0, str|0, ''|0) """ if not context: context = {} - def _replace_field(x): - x = re.sub('([a-z0-9A-Z_])\\.id$', '\\1/.id', x) - return x.replace(':id','/id').split('/') - fields = map(_replace_field, fields) + fields = map(fix_import_export_id_paths, fields) logger = netsvc.Logger() ir_model_data_obj = self.pool.get('ir.model.data') @@ -1102,7 +1230,7 @@ class orm_template(object): if line[i] and skip: return False continue - + #set the mode for m2o, o2m, m2m : xml_id/id/name if len(field) == len(prefix)+1: mode = False @@ -1115,7 +1243,7 @@ class orm_template(object): for db_id in line.split(config.get('csv_internal_sep')): res.append(_get_id(relation, db_id, current_module, mode)) return [(6,0,res)] - + # ID of the record using a XML ID if field[len(prefix)]=='id': try: @@ -1139,9 +1267,9 @@ class orm_template(object): relation_obj = self.pool.get(relation) newfd = relation_obj.fields_get( cr, uid, context=context ) pos = position - + res = many_ids(line[i], relation, current_module, mode) - + first = 0 while pos < len(datas): res2 = process_liness(self, datas, prefix + [field[len(prefix)]], current_module, relation_obj._name, newfd, pos, first) @@ -1151,15 +1279,15 @@ class orm_template(object): nbrmax = max(nbrmax, pos) warning += w2 first += 1 - + if data_res_id2: res.append((4, data_res_id2)) - + if (not newrow) or not reduce(lambda x, y: x or y, newrow.values(), 0): break res.append( (data_res_id2 and 1 or 0, data_res_id2 or 0, newrow) ) - + elif fields_def[field[len(prefix)]]['type']=='many2one': relation = fields_def[field[len(prefix)]]['relation'] @@ -1188,7 +1316,7 @@ class orm_template(object): else: res = line[i] - + row[field[len(prefix)]] = res or False result = (row, nbrmax, warning, data_res_id, xml_id) @@ -1202,7 +1330,7 @@ class orm_template(object): position = 0 while position self._max_count: - # sort by access time to remove only the first/oldest ones in LRU fashion - records = self.datas.items() - records.sort(key=lambda x:x[1]['internal.date_access']) - self.unlink(cr, ROOT_USER_ID, [x[0] for x in records[:len(self.datas)-self._max_count]]) - - return True - - def read(self, cr, user, ids, fields_to_read=None, context=None, load='_classic_read'): - if not context: - context = {} - if not fields_to_read: - fields_to_read = self._columns.keys() - result = [] - if self.datas: - ids_orig = ids - if isinstance(ids, (int, long)): - ids = [ids] - for id in ids: - r = {'id': id} - for f in fields_to_read: - record = self.datas.get(id) - if record: - self._check_access(user, id, 'read') - r[f] = record.get(f, False) - if r[f] and isinstance(self._columns[f], fields.binary) and context.get('bin_size', False): - r[f] = len(r[f]) - result.append(r) - if id in self.datas: - self.datas[id]['internal.date_access'] = time.time() - fields_post = filter(lambda x: x in self._columns and not getattr(self._columns[x], load), fields_to_read) - for f in fields_post: - res2 = self._columns[f].get_memory(cr, self, ids, f, user, context=context, values=result) - for record in result: - record[f] = res2[record['id']] - if isinstance(ids_orig, (int, long)): - return result[0] - return result - - def write(self, cr, user, ids, vals, context=None): - if not ids: - return True - vals2 = {} - upd_todo = [] - for field in vals: - if self._columns[field]._classic_write: - vals2[field] = vals[field] - else: - upd_todo.append(field) - for object_id in ids: - self._check_access(user, object_id, mode='write') - self.datas[object_id].update(vals2) - self.datas[object_id]['internal.date_access'] = time.time() - for field in upd_todo: - self._columns[field].set_memory(cr, self, object_id, field, vals[field], user, context) - self._validate(cr, user, [object_id], context) - wf_service = netsvc.LocalService("workflow") - wf_service.trg_write(user, self._name, object_id, cr) - return object_id - - def create(self, cr, user, vals, context=None): - self.vaccum(cr, user) - self.next_id += 1 - id_new = self.next_id - - vals = self._add_missing_default_values(cr, user, vals, context) - - vals2 = {} - upd_todo = [] - for field in vals: - if self._columns[field]._classic_write: - vals2[field] = vals[field] - else: - upd_todo.append(field) - self.datas[id_new] = vals2 - self.datas[id_new]['internal.date_access'] = time.time() - self.datas[id_new]['internal.create_uid'] = user - - for field in upd_todo: - self._columns[field].set_memory(cr, self, id_new, field, vals[field], user, context) - self._validate(cr, user, [id_new], context) - if self._log_create and not (context and context.get('no_store_function', False)): - message = self._description + \ - " '" + \ - self.name_get(cr, user, [id_new], context=context)[0][1] + \ - "' "+ _("created.") - self.log(cr, user, id_new, message, True, context=context) - wf_service = netsvc.LocalService("workflow") - wf_service.trg_create(user, self._name, id_new, cr) - return id_new - - def _where_calc(self, cr, user, args, active_test=True, context=None): - if not context: - context = {} - args = args[:] - res = [] - # if the object has a field named 'active', filter out all inactive - # records unless they were explicitely asked for - if 'active' in self._columns and (active_test and context.get('active_test', True)): - if args: - active_in_args = False - for a in args: - if a[0] == 'active': - active_in_args = True - if not active_in_args: - args.insert(0, ('active', '=', 1)) - else: - args = [('active', '=', 1)] - if args: - import expression - e = expression.expression(args) - e.parse(cr, user, self, context) - res = e.exp - return res or [] - - def _search(self, cr, user, args, offset=0, limit=None, order=None, context=None, count=False, access_rights_uid=None): - if not context: - context = {} - - # implicit filter on current user except for superuser - if user != 1: - if not args: - args = [] - args.insert(0, ('internal.create_uid', '=', user)) - - result = self._where_calc(cr, user, args, context=context) - if result == []: - return self.datas.keys() - - res = [] - counter = 0 - #Find the value of dict - f = False - if result: - for id, data in self.datas.items(): - counter = counter + 1 - data['id'] = id - if limit and (counter > int(limit)): - break - f = True - for arg in result: - if arg[1] == '=': - val = eval('data[arg[0]]'+'==' +' arg[2]', locals()) - elif arg[1] in ['<', '>', 'in', 'not in', '<=', '>=', '<>']: - val = eval('data[arg[0]]'+arg[1] +' arg[2]', locals()) - elif arg[1] in ['ilike']: - val = (str(data[arg[0]]).find(str(arg[2]))!=-1) - - f = f and val - - if f: - res.append(id) - if count: - return len(res) - return res or [] - - def unlink(self, cr, uid, ids, context=None): - for id in ids: - self._check_access(uid, id, 'unlink') - self.datas.pop(id, None) - if len(ids): - cr.execute('delete from wkf_instance where res_type=%s and res_id IN %s', (self._name, tuple(ids))) - return True - - def perm_read(self, cr, user, ids, context=None, details=True): - result = [] - credentials = self.pool.get('res.users').name_get(cr, user, [user])[0] - create_date = time.strftime('%Y-%m-%d %H:%M:%S') - for id in ids: - self._check_access(user, id, 'read') - result.append({ - 'create_uid': credentials, - 'create_date': create_date, - 'write_uid': False, - 'write_date': False, - 'id': id, - 'xmlid' : False, - }) - return result - - def _check_removed_columns(self, cr, log=False): - # nothing to check in memory... - pass - - def exists(self, cr, uid, ids, context=None): - if isinstance(ids, (long,int)): - ids = [ids] - return [id for id in ids if id in self.datas] - - def check_access_rule(self, cr, uid, ids, operation, context=None): - # ir.rules do not currently apply for orm.memory instances, - # only the implicit visibility=owner one. - for id in ids: - self._check_access(uid, id, operation) - -class orm(orm_template): - _sql_constraints = [] - _table = None - _protected = ['read', 'write', 'create', 'default_get', 'perm_read', 'unlink', 'fields_get', 'fields_view_get', 'search', 'name_get', 'distinct_field_get', 'name_search', 'copy', 'import_data', 'search_count', 'exists'] - __logger = logging.getLogger('orm') - __schema = logging.getLogger('orm.schema') def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, context=None, orderby=False): """ Get the list of records in list view grouped by the given ``groupby`` fields @@ -2564,7 +2315,7 @@ class orm(orm_template): """ context = context or {} - self.pool.get('ir.model.access').check(cr, uid, self._name, 'read') + self.check_read(cr, uid) if not fields: fields = self._columns.keys() @@ -2657,20 +2408,22 @@ class orm(orm_template): del d['id'] return data - def _inherits_join_add(self, parent_model_name, query): + def _inherits_join_add(self, current_table, parent_model_name, query): """ Add missing table SELECT and JOIN clause to ``query`` for reaching the parent table (no duplicates) - + :param current_table: current model object :param parent_model_name: name of the parent model for which the clauses should be added :param query: query object on which the JOIN should be added """ - inherits_field = self._inherits[parent_model_name] + inherits_field = current_table._inherits[parent_model_name] parent_model = self.pool.get(parent_model_name) parent_table_name = parent_model._table quoted_parent_table_name = '"%s"' % parent_table_name if quoted_parent_table_name not in query.tables: query.tables.append(quoted_parent_table_name) - query.where_clause.append('("%s".%s = %s.id)' % (self._table, inherits_field, parent_table_name)) + query.where_clause.append('(%s.%s = %s.id)' % (current_table._table, inherits_field, parent_table_name)) + + def _inherits_join_calc(self, field, query): """ @@ -2685,7 +2438,7 @@ class orm(orm_template): while field in current_table._inherit_fields and not field in current_table._columns: parent_model_name = current_table._inherit_fields[field][0] parent_table = self.pool.get(parent_model_name) - self._inherits_join_add(parent_model_name, query) + self._inherits_join_add(current_table, parent_model_name, query) current_table = parent_table return '"%s".%s' % (current_table._table, field) @@ -2726,7 +2479,7 @@ class orm(orm_template): while ids_lst: iids = ids_lst[:40] ids_lst = ids_lst[40:] - res = f.get(cr, self, iids, k, ROOT_USER_ID, {}) + res = f.get(cr, self, iids, k, SUPERUSER_ID, {}) for key, val in res.items(): if f._multi: val = val[k] @@ -2747,7 +2500,7 @@ class orm(orm_template): pass if not val_id: raise except_orm(_('ValidateError'), - _('Invalid value for reference field "%s" (last part must be a non-zero integer): "%s"') % (field, value)) + _('Invalid value for reference field "%s.%s" (last part must be a non-zero integer): "%s"') % (self._table, field, value)) val = val_model else: val = value @@ -2757,13 +2510,13 @@ class orm(orm_template): elif val in dict(self._columns[field].selection(self, cr, uid, context=context)): return raise except_orm(_('ValidateError'), - _('The value "%s" for the field "%s" is not in the selection') % (value, field)) + _('The value "%s" for the field "%s.%s" is not in the selection') % (value, self._table, field)) def _check_removed_columns(self, cr, log=False): # iterate on the database columns to drop the NOT NULL constraints # of fields which were required but have been removed (or will be added by another module) columns = [c for c in self._columns if not (isinstance(self._columns[c], fields.function) and not self._columns[c].store)] - columns += ('id', 'write_uid', 'write_date', 'create_uid', 'create_date') # openerp access columns + columns += MAGIC_COLUMNS cr.execute("SELECT a.attname, a.attnotnull" " FROM pg_class c, pg_attribute a" " WHERE c.relname=%s" @@ -2781,6 +2534,25 @@ class orm(orm_template): self.__schema.debug("Table '%s': column '%s': dropped NOT NULL constraint", self._table, column['attname']) + # checked version: for direct m2o starting from `self` + def _m2o_add_foreign_key_checked(self, source_field, dest_model, ondelete): + assert self.is_transient() or not dest_model.is_transient(), \ + 'Many2One relationships from non-transient Model to TransientModel are forbidden' + if self.is_transient() and not dest_model.is_transient(): + # TransientModel relationships to regular Models are annoying + # usually because they could block deletion due to the FKs. + # So unless stated otherwise we default them to ondelete=cascade. + ondelete = ondelete or 'cascade' + self._foreign_keys.append((self._table, source_field, dest_model._table, ondelete or 'set null')) + self.__schema.debug("Table '%s': added foreign key '%s' with definition=REFERENCES \"%s\" ON DELETE %s", + self._table, source_field, dest_model._table, ondelete) + + # unchecked version: for custom cases, such as m2m relationships + def _m2o_add_foreign_key_unchecked(self, source_table, source_field, dest_model, ondelete): + self._foreign_keys.append((source_table, source_field, dest_model._table, ondelete or 'set null')) + self.__schema.debug("Table '%s': added foreign key '%s' with definition=REFERENCES \"%s\" ON DELETE %s", + source_table, source_field, dest_model._table, ondelete) + def _auto_init(self, cr, context=None): """ @@ -2830,7 +2602,7 @@ class orm(orm_template): column_data = self._select_column_data(cr) for k, f in self._columns.iteritems(): - if k in ('id', 'write_uid', 'write_date', 'create_uid', 'create_date'): + if k in MAGIC_COLUMNS: continue # Don't update custom (also called manual) fields if f.manual and not update_custom_fields: @@ -2923,7 +2695,7 @@ class orm(orm_template): cr.execute('ALTER TABLE "%s" ALTER COLUMN "%s" DROP NOT NULL' % (self._table, k)) cr.execute('ALTER TABLE "%s" RENAME COLUMN "%s" TO "%s"' % (self._table, k, newname)) cr.execute('ALTER TABLE "%s" ADD COLUMN "%s" %s' % (self._table, k, get_pg_type(f)[1])) - cr.execute("COMMENT ON COLUMN %s.%s IS '%s'" % (self._table, k, f.string.replace("'", "''"))) + cr.execute("COMMENT ON COLUMN %s.\"%s\" IS %%s" % (self._table, k), (f.string,)) self.__schema.debug("Table '%s': column '%s' has changed type (DB=%s, def=%s), data moved to column %s !", self._table, k, f_pg_type, f._type, newname) @@ -2932,7 +2704,7 @@ class orm(orm_template): # set the field to the default value if any if k in self._defaults: if callable(self._defaults[k]): - default = self._defaults[k](self, cr, ROOT_USER_ID, context) + default = self._defaults[k](self, cr, SUPERUSER_ID, context) else: default = self._defaults[k] @@ -2979,7 +2751,8 @@ class orm(orm_template): self.__schema.debug(msg, self._table, k, f._type) if isinstance(f, fields.many2one): - ref = self.pool.get(f._obj)._table + dest_model = self.pool.get(f._obj) + ref = dest_model._table if ref != 'ir_actions': cr.execute('SELECT confdeltype, conname FROM pg_constraint as con, pg_class as cl1, pg_class as cl2, ' 'pg_attribute as att1, pg_attribute as att2 ' @@ -2998,9 +2771,9 @@ class orm(orm_template): "AND con.contype = 'f'", (self._table, ref, k, 'id')) res2 = cr.dictfetchall() if res2: - if res2[0]['confdeltype'] != POSTGRES_CONFDELTYPES.get(f.ondelete.upper(), 'a'): + if res2[0]['confdeltype'] != POSTGRES_CONFDELTYPES.get((f.ondelete or 'set null').upper(), 'a'): cr.execute('ALTER TABLE "' + self._table + '" DROP CONSTRAINT "' + res2[0]['conname'] + '"') - self._foreign_keys.append((self._table, k, ref, f.ondelete)) + self._m2o_add_foreign_key_checked(k, dest_model, f.ondelete) cr.commit() self.__schema.debug("Table '%s': column '%s': XXX", self._table, k) @@ -3010,14 +2783,14 @@ class orm(orm_template): if not isinstance(f, fields.function) or f.store: # add the missing field cr.execute('ALTER TABLE "%s" ADD COLUMN "%s" %s' % (self._table, k, get_pg_type(f)[1])) - cr.execute("COMMENT ON COLUMN %s.%s IS '%s'" % (self._table, k, f.string.replace("'", "''"))) + cr.execute("COMMENT ON COLUMN %s.\"%s\" IS %%s" % (self._table, k), (f.string,)) self.__schema.debug("Table '%s': added column '%s' with definition=%s", self._table, k, get_pg_type(f)[1]) # initialize it if not create and k in self._defaults: if callable(self._defaults[k]): - default = self._defaults[k](self, cr, ROOT_USER_ID, context) + default = self._defaults[k](self, cr, SUPERUSER_ID, context) else: default = self._defaults[k] @@ -3038,12 +2811,11 @@ class orm(orm_template): if isinstance(f, fields.many2one): if not self.pool.get(f._obj): raise except_orm('Programming Error', ('There is no reference available for %s') % (f._obj,)) - ref = self.pool.get(f._obj)._table + dest_model = self.pool.get(f._obj) + ref = dest_model._table # ir_actions is inherited so foreign key doesn't work on it if ref != 'ir_actions': - self._foreign_keys.append((self._table, k, ref, f.ondelete)) - self.__schema.debug("Table '%s': added foreign key '%s' with definition=REFERENCES \"%s\" ON DELETE %s", - self._table, k, ref, f.ondelete) + self._m2o_add_foreign_key_checked(k, dest_model, f.ondelete) if f.select: cr.execute('CREATE INDEX "%s_%s_index" ON "%s" ("%s")' % (self._table, k, self._table, k)) if f.required: @@ -3093,7 +2865,7 @@ class orm(orm_template): def _create_table(self, cr): cr.execute('CREATE TABLE "%s" (id SERIAL NOT NULL, PRIMARY KEY(id)) WITHOUT OIDS' % (self._table,)) - cr.execute("COMMENT ON TABLE \"%s\" IS '%s'" % (self._table, self._description.replace("'", "''"))) + cr.execute(("COMMENT ON TABLE \"%s\" IS %%s" % self._table), (self._description,)) self.__schema.debug("Table '%s': created", self._table) @@ -3132,23 +2904,17 @@ class orm(orm_template): def _add_log_columns(self, cr): - logs = { - 'create_uid': 'INTEGER REFERENCES res_users ON DELETE SET NULL', - 'create_date': 'TIMESTAMP', - 'write_uid': 'INTEGER REFERENCES res_users ON DELETE SET NULL', - 'write_date': 'TIMESTAMP' - } - for k in logs: + for field, field_def in LOG_ACCESS_COLUMNS.iteritems(): cr.execute(""" SELECT c.relname FROM pg_class c, pg_attribute a WHERE c.relname=%s AND a.attname=%s AND c.oid=a.attrelid - """, (self._table, k)) + """, (self._table, field)) if not cr.rowcount: - cr.execute('ALTER TABLE "%s" ADD COLUMN "%s" %s' % (self._table, k, logs[k])) + cr.execute('ALTER TABLE "%s" ADD COLUMN "%s" %s' % (self._table, field, field_def)) cr.commit() self.__schema.debug("Table '%s': added column '%s' with definition=%s", - self._table, k, logs[k]) + self._table, field, field_def) def _select_column_data(self, cr): @@ -3171,20 +2937,28 @@ class orm(orm_template): def _m2m_raise_or_create_relation(self, cr, f): - cr.execute("SELECT relname FROM pg_class WHERE relkind IN ('r','v') AND relname=%s", (f._rel,)) + m2m_tbl, col1, col2 = f._sql_names(self) + cr.execute("SELECT relname FROM pg_class WHERE relkind IN ('r','v') AND relname=%s", (m2m_tbl,)) if not cr.dictfetchall(): if not self.pool.get(f._obj): - raise except_orm('Programming Error', ('There is no reference available for %s') % (f._obj,)) - ref = self.pool.get(f._obj)._table - cr.execute('CREATE TABLE "%s" ("%s" INTEGER NOT NULL, "%s" INTEGER NOT NULL, UNIQUE("%s","%s")) WITH OIDS' % (f._rel, f._id1, f._id2, f._id1, f._id2)) - self._foreign_keys.append((f._rel, f._id1, self._table, 'CASCADE')) - self._foreign_keys.append((f._rel, f._id2, ref, 'CASCADE')) - cr.execute('CREATE INDEX "%s_%s_index" ON "%s" ("%s")' % (f._rel, f._id1, f._rel, f._id1)) - cr.execute('CREATE INDEX "%s_%s_index" ON "%s" ("%s")' % (f._rel, f._id2, f._rel, f._id2)) - cr.execute("COMMENT ON TABLE \"%s\" IS 'RELATION BETWEEN %s AND %s'" % (f._rel, self._table, ref)) + raise except_orm('Programming Error', ('Many2Many destination model does not exist: `%s`') % (f._obj,)) + dest_model = self.pool.get(f._obj) + ref = dest_model._table + cr.execute('CREATE TABLE "%s" ("%s" INTEGER NOT NULL, "%s" INTEGER NOT NULL, UNIQUE("%s","%s")) WITH OIDS' % (m2m_tbl, col1, col2, col1, col2)) + + # create foreign key references with ondelete=cascade, unless the targets are SQL views + cr.execute("SELECT relkind FROM pg_class WHERE relkind IN ('v') AND relname=%s", (ref,)) + if not cr.fetchall(): + self._m2o_add_foreign_key_unchecked(m2m_tbl, col2, dest_model, 'cascade') + cr.execute("SELECT relkind FROM pg_class WHERE relkind IN ('v') AND relname=%s", (self._table,)) + if not cr.fetchall(): + self._m2o_add_foreign_key_unchecked(m2m_tbl, col1, self, 'cascade') + + cr.execute('CREATE INDEX "%s_%s_index" ON "%s" ("%s")' % (m2m_tbl, col1, m2m_tbl, col1)) + cr.execute('CREATE INDEX "%s_%s_index" ON "%s" ("%s")' % (m2m_tbl, col2, m2m_tbl, col2)) + cr.execute("COMMENT ON TABLE \"%s\" IS 'RELATION BETWEEN %s AND %s'" % (m2m_tbl, self._table, ref)) cr.commit() - self.__schema.debug("Create table '%s': relation between '%s' and '%s'", - f._rel, self._table, ref) + self.__schema.debug("Create table '%s': m2m relation between '%s' and '%s'", m2m_tbl, self._table, ref) def _add_sql_constraints(self, cr): @@ -3252,109 +3026,6 @@ class orm(orm_template): cr.execute(line2) cr.commit() - - @classmethod - def createInstance(cls, pool, cr): - return cls.makeInstance(pool, cr, ['_columns', '_defaults', - '_inherits', '_constraints', '_sql_constraints']) - - def __init__(self, pool, cr): - """ - - - copy the stored fields' functions in the osv_pool, - - update the _columns with the fields found in ir_model_fields, - - ensure there is a many2one for each _inherits'd parent, - - update the children's _columns, - - give a chance to each field to initialize itself. - - """ - super(orm, self).__init__(pool, cr) - - if not hasattr(self, '_log_access'): - # if not access is not specify, it is the same value as _auto - self._log_access = getattr(self, "_auto", True) - - self._columns = self._columns.copy() - for store_field in self._columns: - f = self._columns[store_field] - if hasattr(f, 'digits_change'): - f.digits_change(cr) - if not isinstance(f, fields.function): - continue - if not f.store: - continue - if self._columns[store_field].store is True: - sm = {self._name: (lambda self, cr, uid, ids, c={}: ids, None, 10, None)} - else: - sm = self._columns[store_field].store - for object, aa in sm.items(): - if len(aa) == 4: - (fnct, fields2, order, length) = aa - elif len(aa) == 3: - (fnct, fields2, order) = aa - length = None - else: - raise except_orm('Error', - ('Invalid function definition %s in object %s !\nYou must use the definition: store={object:(fnct, fields, priority, time length)}.' % (store_field, self._name))) - self.pool._store_function.setdefault(object, []) - ok = True - for x, y, z, e, f, l in self.pool._store_function[object]: - if (x==self._name) and (y==store_field) and (e==fields2): - if f == order: - ok = False - if ok: - self.pool._store_function[object].append( (self._name, store_field, fnct, fields2, order, length)) - self.pool._store_function[object].sort(lambda x, y: cmp(x[4], y[4])) - - for (key, _, msg) in self._sql_constraints: - self.pool._sql_error[self._table+'_'+key] = msg - - # Load manual fields - - cr.execute("SELECT id FROM ir_model_fields WHERE name=%s AND model=%s", ('state', 'ir.model.fields')) - if cr.fetchone(): - cr.execute('SELECT * FROM ir_model_fields WHERE model=%s AND state=%s', (self._name, 'manual')) - for field in cr.dictfetchall(): - if field['name'] in self._columns: - continue - attrs = { - 'string': field['field_description'], - 'required': bool(field['required']), - 'readonly': bool(field['readonly']), - 'domain': eval(field['domain']) if field['domain'] else None, - 'size': field['size'], - 'ondelete': field['on_delete'], - 'translate': (field['translate']), - 'manual': True, - #'select': int(field['select_level']) - } - - if field['ttype'] == 'selection': - self._columns[field['name']] = fields.selection(eval(field['selection']), **attrs) - elif field['ttype'] == 'reference': - self._columns[field['name']] = fields.reference(selection=eval(field['selection']), **attrs) - elif field['ttype'] == 'many2one': - self._columns[field['name']] = fields.many2one(field['relation'], **attrs) - elif field['ttype'] == 'one2many': - self._columns[field['name']] = fields.one2many(field['relation'], field['relation_field'], **attrs) - elif field['ttype'] == 'many2many': - _rel1 = field['relation'].replace('.', '_') - _rel2 = field['model'].replace('.', '_') - _rel_name = 'x_%s_%s_%s_rel' % (_rel1, _rel2, field['name']) - self._columns[field['name']] = fields.many2many(field['relation'], _rel_name, 'id1', 'id2', **attrs) - else: - self._columns[field['name']] = getattr(fields, field['ttype'])(**attrs) - self._inherits_check() - self._inherits_reload() - if not self._sequence: - self._sequence = self._table + '_id_seq' - for k in self._defaults: - assert (k in self._columns) or (k in self._inherit_fields), 'Default function defined in %s but field %s does not exist !' % (self._name, k,) - for f in self._columns: - self._columns[f].restart() - - __init__.__doc__ = orm_template.__init__.__doc__ + __init__.__doc__ - # # Update objects that uses this one to update their _inherits fields # @@ -3376,9 +3047,9 @@ class orm(orm_template): for table in self._inherits: other = self.pool.get(table) for col in other._columns.keys(): - res[col] = (table, self._inherits[table], other._columns[col]) + res[col] = (table, self._inherits[table], other._columns[col], table) for col in other._inherit_fields.keys(): - res[col] = (table, self._inherits[table], other._inherit_fields[col][2]) + res[col] = (table, self._inherits[table], other._inherit_fields[col][2], other._inherit_fields[col][3]) self._inherit_fields = res self._all_columns = self._get_column_infos() self._inherits_reload_src() @@ -3389,8 +3060,8 @@ class orm(orm_template): inherited field via _inherits) to a ``column_info`` struct giving detailed columns """ result = {} - for k, (parent, m2o, col) in self._inherit_fields.iteritems(): - result[k] = fields.column_info(k, col, parent, m2o) + for k, (parent, m2o, col, original_parent) in self._inherit_fields.iteritems(): + result[k] = fields.column_info(k, col, parent, m2o, original_parent) for k, col in self._columns.iteritems(): result[k] = fields.column_info(k, col) return result @@ -3433,9 +3104,12 @@ class orm(orm_template): # return _proxy - def fields_get(self, cr, user, fields=None, context=None): - """ - Get the description of list of fields + def fields_get(self, cr, user, allfields=None, context=None, write_access=True): + """ Return the definition of each field. + + The returned value is a dictionary (indiced by field name) of + dictionaries. The _inherits'd fields are included. The string, help, + and selection (if present) attributes are translated. :param cr: database cursor :param user: current user id @@ -3445,15 +3119,74 @@ class orm(orm_template): :raise AccessError: * if user has no create/write rights on the requested object """ - ira = self.pool.get('ir.model.access') - write_access = ira.check(cr, user, self._name, 'write', False) or \ - ira.check(cr, user, self._name, 'create', False) - return super(orm, self).fields_get(cr, user, fields, context, write_access) + if context is None: + context = {} + + write_access = self.check_write(cr, user, False) or \ + self.check_create(cr, user, False) + + res = {} + + translation_obj = self.pool.get('ir.translation') + for parent in self._inherits: + res.update(self.pool.get(parent).fields_get(cr, user, allfields, context)) + + for f, field in self._columns.iteritems(): + if allfields and f not in allfields: + continue + + res[f] = fields.field_to_dict(self, cr, user, context, field) + + if not write_access: + res[f]['readonly'] = True + res[f]['states'] = {} + + if 'string' in res[f]: + res_trans = translation_obj._get_source(cr, user, self._name + ',' + f, 'field', context.get('lang', False) or 'en_US') + if res_trans: + res[f]['string'] = res_trans + if 'help' in res[f]: + help_trans = translation_obj._get_source(cr, user, self._name + ',' + f, 'help', context.get('lang', False) or 'en_US') + if help_trans: + res[f]['help'] = help_trans + if 'selection' in res[f]: + if isinstance(field.selection, (tuple, list)): + sel = field.selection + sel2 = [] + for key, val in sel: + val2 = None + if val: + val2 = translation_obj._get_source(cr, user, self._name + ',' + f, 'selection', context.get('lang', False) or 'en_US', val) + sel2.append((key, val2 or val)) + res[f]['selection'] = sel2 + + return res def read(self, cr, user, ids, fields=None, context=None, load='_classic_read'): + """ Read records with given ids with the given fields + + :param cr: database cursor + :param user: current user id + :param ids: id or list of the ids of the records to read + :param fields: optional list of field names to return (default: all fields would be returned) + :type fields: list (example ['field_name_1', ...]) + :param context: optional context dictionary - it may contains keys for specifying certain options + like ``context_lang``, ``context_tz`` to alter the results of the call. + A special ``bin_size`` boolean flag may also be passed in the context to request the + value of all fields.binary columns to be returned as the size of the binary instead of its + contents. This can also be selectively overriden by passing a field-specific flag + in the form ``bin_size_XXX: True/False`` where ``XXX`` is the name of the field. + Note: The ``bin_size_XXX`` form is new in OpenERP v6.0. + :return: list of dictionaries((dictionary per record asked)) with requested field values + :rtype: [{‘name_of_the_field’: value, ...}, ...] + :raise AccessError: * if user has no read rights on the requested object + * if user tries to bypass access rules for read on the requested object + + """ + if not context: context = {} - self.pool.get('ir.model.access').check(cr, user, self._name, 'read') + self.check_read(cr, user) if not fields: fields = list(set(self._columns.keys() + self._inherit_fields.keys())) if isinstance(ids, (int, long)): @@ -3494,7 +3227,7 @@ class orm(orm_template): res = [] if len(fields_pre): def convert_field(f): - f_qual = "%s.%s" % (self._table, f) # need fully-qualified references in case len(tables) > 1 + f_qual = '%s."%s"' % (self._table, f) # need fully-qualified references in case len(tables) > 1 if f in ('create_date', 'write_date'): return "date_trunc('second', %s) as %s" % (f_qual, f) if f == self.CONCURRENCY_CHECK_FIELD: @@ -3627,6 +3360,7 @@ class orm(orm_template): vals[field] = False return res + # TODO check READ access def perm_read(self, cr, user, ids, context=None, details=True): """ Returns some metadata about the given records. @@ -3696,6 +3430,23 @@ class orm(orm_template): # mention the first one only to keep the error message readable raise except_orm('ConcurrencyException', _('A document was modified since you last viewed it (%s:%d)') % (self._description, res[0])) + def check_access_rights(self, cr, uid, operation, raise_exception=True): # no context on purpose. + """Verifies that the operation given by ``operation`` is allowed for the user + according to the access rights.""" + return self.pool.get('ir.model.access').check(cr, uid, self._name, operation, raise_exception) + + def check_create(self, cr, uid, raise_exception=True): + return self.check_access_rights(cr, uid, 'create', raise_exception) + + def check_read(self, cr, uid, raise_exception=True): + return self.check_access_rights(cr, uid, 'read', raise_exception) + + def check_unlink(self, cr, uid, raise_exception=True): + return self.check_access_rights(cr, uid, 'unlink', raise_exception) + + def check_write(self, cr, uid, raise_exception=True): + return self.check_access_rights(cr, uid, 'write', raise_exception) + def check_access_rule(self, cr, uid, ids, operation, context=None): """Verifies that the operation given by ``operation`` is allowed for the user according to ir.rules. @@ -3704,17 +3455,35 @@ class orm(orm_template): :raise except_orm: * if current ir.rules do not permit this operation. :return: None if the operation is allowed """ - where_clause, where_params, tables = self.pool.get('ir.rule').domain_get(cr, uid, self._name, operation, context=context) - if where_clause: - where_clause = ' and ' + ' and '.join(where_clause) - for sub_ids in cr.split_for_in_conditions(ids): - cr.execute('SELECT ' + self._table + '.id FROM ' + ','.join(tables) + - ' WHERE ' + self._table + '.id IN %s' + where_clause, - [sub_ids] + where_params) - if cr.rowcount != len(sub_ids): - raise except_orm(_('AccessError'), - _('Operation prohibited by access rules, or performed on an already deleted document (Operation: %s, Document type: %s).') - % (operation, self._description)) + if uid == SUPERUSER_ID: + return + + if self.is_transient: + # Only one single implicit access rule for transient models: owner only! + # This is ok to hardcode because we assert that TransientModels always + # have log_access enabled and this the create_uid column is always there. + # And even with _inherits, these fields are always present in the local + # table too, so no need for JOINs. + cr.execute("""SELECT distinct create_uid + FROM %s + WHERE id IN %%s""" % self._table, (tuple(ids),)) + uids = [x[0] for x in cr.fetchall()] + if len(uids) != 1 or uids[0] != uid: + raise orm.except_orm(_('AccessError'), '%s access is ' + 'restricted to your own records for transient models ' + '(except for the super-user).' % operation.capitalize()) + else: + where_clause, where_params, tables = self.pool.get('ir.rule').domain_get(cr, uid, self._name, operation, context=context) + if where_clause: + where_clause = ' and ' + ' and '.join(where_clause) + for sub_ids in cr.split_for_in_conditions(ids): + cr.execute('SELECT ' + self._table + '.id FROM ' + ','.join(tables) + + ' WHERE ' + self._table + '.id IN %s' + where_clause, + [sub_ids] + where_params) + if cr.rowcount != len(sub_ids): + raise except_orm(_('AccessError'), + _('Operation prohibited by access rules, or performed on an already deleted document (Operation: %s, Document type: %s).') + % (operation, self._description)) def unlink(self, cr, uid, ids, context=None): """ @@ -3739,7 +3508,7 @@ class orm(orm_template): self._check_concurrency(cr, ids, context) - self.pool.get('ir.model.access').check(cr, uid, self._name, 'unlink') + self.check_unlink(cr, uid) properties = self.pool.get('ir.property') domain = [('res_id', '=', False), @@ -3765,10 +3534,10 @@ class orm(orm_template): # Note: following steps performed as admin to avoid access rights restrictions, and with no context # to avoid possible side-effects during admin calls. # Step 1. Calling unlink of ir_model_data only for the affected IDS - reference_ids = pool_model_data.search(cr, ROOT_USER_ID, [('res_id','in',list(sub_ids)),('model','=',self._name)]) + reference_ids = pool_model_data.search(cr, SUPERUSER_ID, [('res_id','in',list(sub_ids)),('model','=',self._name)]) # Step 2. Marching towards the real deletion of referenced records if reference_ids: - pool_model_data.unlink(cr, ROOT_USER_ID, reference_ids) + pool_model_data.unlink(cr, SUPERUSER_ID, reference_ids) # For the same reason, removing the record relevant to ir_values ir_value_ids = ir_values_obj.search(cr, uid, @@ -3876,7 +3645,7 @@ class orm(orm_template): ids = [ids] self._check_concurrency(cr, ids, context) - self.pool.get('ir.model.access').check(cr, user, self._name, 'write') + self.check_write(cr, user) result = self._store_get_values(cr, user, ids, vals.keys(), context) or [] @@ -4085,7 +3854,11 @@ class orm(orm_template): """ if not context: context = {} - self.pool.get('ir.model.access').check(cr, user, self._name, 'create') + + if self.is_transient(): + self._transient_vacuum(cr, user) + + self.check_create(cr, user) vals = self._add_missing_default_values(cr, user, vals, context) @@ -4099,7 +3872,7 @@ class orm(orm_template): upd_todo = [] for v in vals.keys(): if v in self._inherit_fields: - (table, col, col_detail) = self._inherit_fields[v] + (table, col, col_detail, original_parent) = self._inherit_fields[v] tocreate[table][v] = vals[v] del vals[v] else: @@ -4238,6 +4011,27 @@ class orm(orm_template): wf_service.trg_create(user, self._name, id_new, cr) return id_new + def browse(self, cr, uid, select, context=None, list_class=None, fields_process=None): + """Fetch records as objects allowing to use dot notation to browse fields and relations + + :param cr: database cursor + :param user: current user id + :param select: id or list of ids. + :param context: context arguments, like lang, time zone + :rtype: object or list of objects requested + + """ + self._list_class = list_class or browse_record_list + cache = {} + # need to accepts ints and longs because ids coming from a method + # launched by button in the interface have a type long... + if isinstance(select, (int, long)): + return browse_record(cr, uid, select, self, cache, context=context, list_class=self._list_class, fields_process=fields_process) + elif isinstance(select, list): + return self._list_class([browse_record(cr, uid, id, self, cache, context=context, list_class=self._list_class, fields_process=fields_process) for id in select], context=context) + else: + return browse_null() + def _store_get_values(self, cr, uid, ids, fields, context): """Returns an ordered list of fields.functions to call due to an update operation on ``fields`` of records with ``ids``, @@ -4246,44 +4040,52 @@ class orm(orm_template): :return: [(priority, model_name, [record_ids,], [function_fields,])] """ - # FIXME: rewrite, cleanup, use real variable names - # e.g.: http://pastie.org/1222060 - result = {} - fncts = self.pool._store_function.get(self._name, []) - for fnct in range(len(fncts)): - if fncts[fnct][3]: - ok = False - if not fields: - ok = True - for f in (fields or []): - if f in fncts[fnct][3]: - ok = True - break - if not ok: - continue + if fields is None: fields = [] + stored_functions = self.pool._store_function.get(self._name, []) - result.setdefault(fncts[fnct][0], {}) + # use indexed names for the details of the stored_functions: + model_name_, func_field_to_compute_, id_mapping_fnct_, trigger_fields_, priority_ = range(5) + # only keep functions that should be triggered for the ``fields`` + # being written to. + to_compute = [f for f in stored_functions \ + if ((not f[trigger_fields_]) or set(fields).intersection(f[trigger_fields_]))] + + mapping = {} + for function in to_compute: # use admin user for accessing objects having rules defined on store fields - ids2 = fncts[fnct][2](self, cr, ROOT_USER_ID, ids, context) - for id in filter(None, ids2): - result[fncts[fnct][0]].setdefault(id, []) - result[fncts[fnct][0]][id].append(fnct) - dict = {} - for object in result: - k2 = {} - for id, fnct in result[object].items(): - k2.setdefault(tuple(fnct), []) - k2[tuple(fnct)].append(id) - for fnct, id in k2.items(): - dict.setdefault(fncts[fnct[0]][4], []) - dict[fncts[fnct[0]][4]].append((fncts[fnct[0]][4], object, id, map(lambda x: fncts[x][1], fnct))) - result2 = [] - tmp = dict.keys() - tmp.sort() - for k in tmp: - result2 += dict[k] - return result2 + target_ids = [id for id in function[id_mapping_fnct_](self, cr, SUPERUSER_ID, ids, context) if id] + + # the compound key must consider the priority and model name + key = (function[priority_], function[model_name_]) + for target_id in target_ids: + mapping.setdefault(key, {}).setdefault(target_id,set()).add(tuple(function)) + + # Here mapping looks like: + # { (10, 'model_a') : { target_id1: [ (function_1_tuple, function_2_tuple) ], ... } + # (20, 'model_a') : { target_id2: [ (function_3_tuple, function_4_tuple) ], ... } + # (99, 'model_a') : { target_id1: [ (function_5_tuple, function_6_tuple) ], ... } + # } + + # Now we need to generate the batch function calls list + # call_map = + # { (10, 'model_a') : [(10, 'model_a', [record_ids,], [function_fields,])] } + call_map = {} + for ((priority,model), id_map) in mapping.iteritems(): + functions_ids_maps = {} + # function_ids_maps = + # { (function_1_tuple, function_2_tuple) : [target_id1, target_id2, ..] } + for id, functions in id_map.iteritems(): + functions_ids_maps.setdefault(tuple(functions), []).append(id) + for functions, ids in functions_ids_maps.iteritems(): + call_map.setdefault((priority,model),[]).append((priority, model, ids, + [f[func_field_to_compute_] for f in functions])) + ordered_keys = call_map.keys() + ordered_keys.sort() + result = [] + if ordered_keys: + result = reduce(operator.add, (call_map[k] for k in ordered_keys)) + return result def _store_set_values(self, cr, uid, ids, fields, context): """Calls the fields.function's "implementation function" for all ``fields``, on records with ``ids`` (taking care of @@ -4319,7 +4121,7 @@ class orm(orm_template): val = todo[key] if key: # use admin user for accessing objects having rules defined on store fields - result = self._columns[val[0]].get(cr, self, ids, val, ROOT_USER_ID, context=context) + result = self._columns[val[0]].get(cr, self, ids, val, SUPERUSER_ID, context=context) for id, value in result.items(): if field_flag: for f in value.keys(): @@ -4345,7 +4147,7 @@ class orm(orm_template): else: for f in val: # use admin user for accessing objects having rules defined on store fields - result = self._columns[f].get(cr, self, ids, f, ROOT_USER_ID, context=context) + result = self._columns[f].get(cr, self, ids, f, SUPERUSER_ID, context=context) for r in result.keys(): if field_flag: if r in field_dict.keys(): @@ -4394,9 +4196,7 @@ class orm(orm_template): domain = [('active', '=', 1)] if domain: - import expression - e = expression.expression(domain) - e.parse(cr, user, self, context) + e = expression.expression(cr, user, domain, self, context) tables = e.get_tables() where_clause, where_params = e.to_sql() where_clause = where_clause and [where_clause] or [] @@ -4421,7 +4221,7 @@ class orm(orm_template): if parent_model and child_object: # as inherited rules are being applied, we need to add the missing JOIN # to reach the parent table (if it was not JOINed yet in the query) - child_object._inherits_join_add(parent_model, query) + child_object._inherits_join_add(child_object, parent_model, query) query.where_clause += added_clause query.where_clause_params += added_params for table in added_tables: @@ -4510,7 +4310,7 @@ class orm(orm_template): else: continue # ignore non-readable or "non-joinable" fields elif order_field in self._inherit_fields: - parent_obj = self.pool.get(self._inherit_fields[order_field][0]) + parent_obj = self.pool.get(self._inherit_fields[order_field][3]) order_column = parent_obj._columns[order_field] if order_column._classic_read: inner_clause = self._inherits_join_calc(order_field, query) @@ -4541,7 +4341,11 @@ class orm(orm_template): """ if context is None: context = {} - self.pool.get('ir.model.access').check(cr, access_rights_uid or user, self._name, 'read') + self.check_read(cr, access_rights_uid or user) + + # For transient models, restrict acces to the current user, except for the super-user + if self.is_transient() and self._log_access and user != SUPERUSER_ID: + args = expression.AND(([('create_uid', '=', user)], args or [])) query = self._where_calc(cr, user, args, context=context) self._apply_ir_rules(cr, user, query, 'read', context=context) @@ -4617,7 +4421,7 @@ class orm(orm_template): for f in fields: ftype = fields[f]['type'] - if self._log_access and f in ('create_date', 'create_uid', 'write_date', 'write_uid'): + if self._log_access and f in LOG_ACCESS_COLUMNS: del data[f] if f in default: @@ -4654,9 +4458,13 @@ class orm(orm_template): # force a clean recompute! for parent_column in ['parent_left', 'parent_right']: data.pop(parent_column, None) - - for v in self._inherits: - del data[self._inherits[v]] + # Remove _inherits field's from data recursively, missing parents will + # be created by create() (so that copy() copy everything). + def remove_ids(inherits_dict): + for parent_table in inherits_dict: + del data[inherits_dict[parent_table]] + remove_ids(self.pool.get(parent_table)._inherits) + remove_ids(self._inherits) return data def copy_translations(self, cr, uid, old_id, new_id, context=None): @@ -4728,6 +4536,18 @@ class orm(orm_template): return new_id def exists(self, cr, uid, ids, context=None): + """Checks whether the given id or ids exist in this model, + and return the list of ids that do. This is simple to use for + a truth test on a browse_record:: + + if record.exists(): + pass + + :param ids: id or list of ids to check for existence + :type ids: int or [int] + :return: the list of ids that currently exist, out of + the given `ids` + """ if type(ids) in (int, long): ids = [ids] query = 'SELECT id FROM "%s"' % (self._table) @@ -4812,5 +4632,98 @@ class orm(orm_template): results[k] = '' return results -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: + # Transience + def is_transient(self): + """ Return whether the model is transient. + See TransientModel. + + """ + return self._transient + + def _transient_clean_rows_older_than(self, cr, seconds): + assert self._transient, "Model %s is not transient, it cannot be vacuumed!" % self._name + cr.execute("SELECT id FROM " + self._table + " WHERE" + " COALESCE(write_date, create_date, now())::timestamp <" + " (now() - interval %s)", ("%s seconds" % seconds,)) + ids = [x[0] for x in cr.fetchall()] + self.unlink(cr, SUPERUSER_ID, ids) + + def _transient_clean_old_rows(self, cr, count): + assert self._transient, "Model %s is not transient, it cannot be vacuumed!" % self._name + cr.execute( + "SELECT id, COALESCE(write_date, create_date, now())::timestamp" + " AS t FROM " + self._table + + " ORDER BY t LIMIT %s", (count,)) + ids = [x[0] for x in cr.fetchall()] + self.unlink(cr, SUPERUSER_ID, ids) + + def _transient_vacuum(self, cr, uid, force=False): + """Clean the transient records. + + This unlinks old records from the transient model tables whenever the + "_transient_max_count" or "_max_age" conditions (if any) are reached. + Actual cleaning will happen only once every "_transient_check_time" calls. + This means this method can be called frequently called (e.g. whenever + a new record is created). + """ + assert self._transient, "Model %s is not transient, it cannot be vacuumed!" % self._name + self._transient_check_count += 1 + if (not force) and (self._transient_check_count % self._transient_check_time): + self._transient_check_count = 0 + return True + + # Age-based expiration + if self._transient_max_hours: + self._transient_clean_rows_older_than(cr, self._transient_max_hours * 60 * 60) + + # Count-based expiration + if self._transient_max_count: + self._transient_clean_old_rows(cr, self._transient_max_count) + + return True + +# keep this import here, at top it will cause dependency cycle errors +import expression + +class Model(BaseModel): + """Main super-class for regular database-persisted OpenERP models. + + OpenERP models are created by inheriting from this class:: + + class user(Model): + ... + + The system will later instantiate the class once per database (on + which the class' module is installed). + """ + _register = False # not visible in ORM registry, meant to be python-inherited only + _transient = False # True in a TransientModel + +class TransientModel(BaseModel): + """Model super-class for transient records, meant to be temporarily + persisted, and regularly vaccuum-cleaned. + + A TransientModel has a simplified access rights management, + all users can create new records, and may only access the + records they created. The super-user has unrestricted access + to all TransientModel records. + """ + _register = False # not visible in ORM registry, meant to be python-inherited only + _transient = True + +class AbstractModel(BaseModel): + """Abstract Model super-class for creating an abstract class meant to be + inherited by regular models (Models or TransientModels) but not meant to + be usable on its own, or persisted. + + Technical note: we don't want to make AbstractModel the super-class of + Model or BaseModel because it would not make sense to put the main + definition of persistence methods such as create() in it, and still we + should be able to override them within an AbstractModel. + """ + _auto = False # don't create any database backend for AbstractModels + _register = False # not visible in ORM registry, meant to be python-inherited only + + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerp/osv/osv.py b/openerp/osv/osv.py index 1327efe5731..7f5894e5146 100644 --- a/openerp/osv/osv.py +++ b/openerp/osv/osv.py @@ -21,31 +21,29 @@ #.apidoc title: Objects Services (OSV) +import logging +from psycopg2 import IntegrityError, errorcodes + import orm +import openerp import openerp.netsvc as netsvc import openerp.pooler as pooler import openerp.sql_db as sql_db -import logging -from psycopg2 import IntegrityError, errorcodes from openerp.tools.func import wraps from openerp.tools.translate import translate -from openerp.osv.orm import MetaModel +from openerp.osv.orm import MetaModel, Model, TransientModel, AbstractModel +import openerp.exceptions +# For backward compatibility +except_osv = openerp.exceptions.Warning -class except_osv(Exception): - def __init__(self, name, value, exc_type='warning'): - self.name = name - self.exc_type = exc_type - self.value = value - self.args = (exc_type, name) +service = None - -class object_proxy(netsvc.Service): +class object_proxy(): def __init__(self): self.logger = logging.getLogger('web-services') - netsvc.Service.__init__(self, 'object_proxy', audience='') - self.exportMethod(self.exec_workflow) - self.exportMethod(self.execute) + global service + service = self def check(f): @wraps(f) @@ -119,14 +117,14 @@ class object_proxy(netsvc.Service): except orm.except_orm, inst: if inst.name == 'AccessError': self.logger.debug("AccessError", exc_info=True) - self.abortResponse(1, inst.name, 'warning', inst.value) + netsvc.abort_response(1, inst.name, 'warning', inst.value) except except_osv, inst: - self.abortResponse(1, inst.name, inst.exc_type, inst.value) + netsvc.abort_response(1, inst.name, 'warning', inst.value) except IntegrityError, inst: osv_pool = pooler.get_pool(dbname) for key in osv_pool._sql_error.keys(): if key in inst[0]: - self.abortResponse(1, _('Constraint Error'), 'warning', + netsvc.abort_response(1, _('Constraint Error'), 'warning', tr(osv_pool._sql_error[key], 'sql_constraint') or inst[0]) if inst.pgcode in (errorcodes.NOT_NULL_VIOLATION, errorcodes.FOREIGN_KEY_VIOLATION, errorcodes.RESTRICT_VIOLATION): msg = _('The operation cannot be completed, probably due to the following:\n- deletion: you may be trying to delete a record while other records still reference it\n- creation/update: a mandatory field is not correctly set') @@ -147,9 +145,9 @@ class object_proxy(netsvc.Service): msg += _('\n\n[object with reference: %s - %s]') % (model_name, model) except Exception: pass - self.abortResponse(1, _('Integrity Error'), 'warning', msg) + netsvc.abort_response(1, _('Integrity Error'), 'warning', msg) else: - self.abortResponse(1, _('Integrity Error'), 'warning', inst[0]) + netsvc.abort_response(1, _('Integrity Error'), 'warning', inst[0]) except Exception: self.logger.exception("Uncaught exception") raise @@ -198,17 +196,10 @@ class object_proxy(netsvc.Service): cr.close() return res - -class osv_memory(orm.orm_memory): - """ Deprecated class. """ - __metaclass__ = MetaModel - _register = False # Set to false if the model shouldn't be automatically discovered. - - -class osv(orm.orm): - """ Deprecated class. """ - __metaclass__ = MetaModel - _register = False # Set to false if the model shouldn't be automatically discovered. +# deprecated - for backward compatibility. +osv = Model +osv_memory = TransientModel +osv_abstract = AbstractModel # ;-) def start_object_proxy(): diff --git a/openerp/pooler.py b/openerp/pooler.py index c754385d6b3..88b60864b90 100644 --- a/openerp/pooler.py +++ b/openerp/pooler.py @@ -34,11 +34,6 @@ def get_db_and_pool(db_name, force_demo=False, status=None, update_module=False, return registry.db, registry -def delete_pool(db_name): - """Delete an existing registry.""" - RegistryManager.delete(db_name) - - def restart_pool(db_name, force_demo=False, status=None, update_module=False): """Delete an existing registry and return a database connection and a newly initialized registry.""" registry = RegistryManager.new(db_name, force_demo, status, update_module, True) diff --git a/openerp/report/custom.py b/openerp/report/custom.py index f3d6cfbc074..051d1f29862 100644 --- a/openerp/report/custom.py +++ b/openerp/report/custom.py @@ -136,16 +136,15 @@ class report_custom(report_int): ids = self.pool.get(report.model_id.model).search(cr, uid, []) datas['ids'] = ids - service = netsvc.LocalService("object_proxy") report_id = datas['report_id'] - report = service.execute(cr.dbname, uid, 'ir.report.custom', 'read', [report_id], context=context)[0] - fields = service.execute(cr.dbname, uid, 'ir.report.custom.fields', 'read', report['fields_child0'], context=context) + report = self.pool.get('ir.report.custom').read(cr, uid, [report_id], context=context)[0] + fields = self.pool.get('ir.report.custom.fields').read(cr, uid, report['fields_child0'], context=context) fields.sort(lambda x,y : x['sequence'] - y['sequence']) if report['field_parent']: - parent_field = service.execute(cr.dbname, uid, 'ir.model.fields', 'read', [report['field_parent'][0]],['model']) - model_name = service.execute(cr.dbname, uid, 'ir.model', 'read', [report['model_id'][0]], ['model'],context=context)[0]['model'] + parent_field = self.pool.get('ir.model.fields').read(cr, uid, [report['field_parent'][0]], ['model']) + model_name = self.pool.get('ir.model').read(cr, uid, [report['model_id'][0]], ['model'], context=context)[0]['model'] fct = {} fct['id'] = lambda x : x @@ -160,9 +159,7 @@ class report_custom(report_int): field_child = f['field_child'+str(i)] if field_child: row.append( - service.execute(cr.dbname, uid, - 'ir.model.fields', 'read', [field_child[0]], - ['name'], context=context)[0]['name'] + self.pool.get('ir.model.fields').read(cr, uid, [field_child[0]], ['name'], context=context)[0]['name'] ) if f['fc'+str(i)+'_operande']: fct_name = 'id' @@ -346,7 +343,7 @@ class report_custom(report_int): def _create_lines(self, cr, uid, ids, report, fields, results, context): - service = netsvc.LocalService("object_proxy") + pool = pooler.get_pool(cr.dbname) pdf_string = cStringIO.StringIO() can = canvas.init(fname=pdf_string, format='pdf') @@ -376,7 +373,7 @@ class report_custom(report_int): for f in fields: field_id = (f['field_child3'] and f['field_child3'][0]) or (f['field_child2'] and f['field_child2'][0]) or (f['field_child1'] and f['field_child1'][0]) or (f['field_child0'] and f['field_child0'][0]) if field_id: - type = service.execute(cr.dbname, uid, 'ir.model.fields', 'read', [field_id],['ttype']) + type = pool.get('ir.model.fields').read(cr, uid, [field_id],['ttype']) if type[0]['ttype'] == 'date': date_idx = idx fct[idx] = process_date[report['frequency']] @@ -449,7 +446,7 @@ class report_custom(report_int): def _create_bars(self, cr, uid, ids, report, fields, results, context): - service = netsvc.LocalService("object_proxy") + pool = pooler.get_pool(cr.dbname) pdf_string = cStringIO.StringIO() can = canvas.init(fname=pdf_string, format='pdf') @@ -475,7 +472,7 @@ class report_custom(report_int): for f in fields: field_id = (f['field_child3'] and f['field_child3'][0]) or (f['field_child2'] and f['field_child2'][0]) or (f['field_child1'] and f['field_child1'][0]) or (f['field_child0'] and f['field_child0'][0]) if field_id: - type = service.execute(cr.dbname, uid, 'ir.model.fields', 'read', [field_id],['ttype']) + type = pool.get('ir.model.fields').read(cr, uid, [field_id],['ttype']) if type[0]['ttype'] == 'date': date_idx = idx fct[idx] = process_date[report['frequency']] diff --git a/openerp/report/interface.py b/openerp/report/interface.py index 178c015ba34..9a97c445671 100644 --- a/openerp/report/interface.py +++ b/openerp/report/interface.py @@ -41,9 +41,9 @@ def toxml(value): return unicode_value.replace('&', '&').replace('<','<').replace('>','>') class report_int(netsvc.Service): - def __init__(self, name, audience='*'): + def __init__(self, name): assert not self.exists(name), 'The report "%s" already exists!' % name - super(report_int, self).__init__(name, audience) + super(report_int, self).__init__(name) if name[0:7]<>'report.': raise Exception, 'ConceptionError, bad report name, should start with "report."' self.name = name @@ -51,8 +51,6 @@ class report_int(netsvc.Service): self.name2 = '.'.join(name.split('.')[1:]) # TODO the reports have methods with a 'title' kwarg that is redundant with this attribute self.title = None - #self.joinGroup('report') - self.exportMethod(self.create) def create(self, cr, uid, ids, datas, context=None): return False @@ -233,6 +231,7 @@ class report_rml(report_int): def _get_path(self): ret = [] ret.append(self.tmpl.replace(os.path.sep, '/').rsplit('/',1)[0]) # Same dir as the report rml + ret.append('addons') ret.append(tools.config['root_path']) return ret diff --git a/openerp/report/preprocess.py b/openerp/report/preprocess.py index c84ce66b472..b339e078d81 100644 --- a/openerp/report/preprocess.py +++ b/openerp/report/preprocess.py @@ -65,7 +65,10 @@ class report(object): if type =='html2html': match = html_parents if txt.group(3): - match = [txt.group(3)] + group_3 = txt.group(3) + if group_3.startswith("'") or group_3.startswith('"'): + group_3 = group_3[1:-1] + match = [group_3] n = node while n.tag not in match: n = n.getparent() diff --git a/openerp/report/print_xml.py b/openerp/report/print_xml.py index ad2b0528d99..b7074a2d0c3 100644 --- a/openerp/report/print_xml.py +++ b/openerp/report/print_xml.py @@ -137,9 +137,8 @@ class document(object): value = self.get_value(browser, attrs['name']) - service = netsvc.LocalService("object_proxy") - ids = service.execute(self.cr.dbname, self.uid, 'ir.attachment', 'search', [('res_model','=',model),('res_id','=',int(value))]) - datas = service.execute(self.cr.dbname, self.uid, 'ir.attachment', 'read', ids) + ids = self.pool.get('ir.attachment').search(self.cr, self.uid, [('res_model','=',model),('res_id','=',int(value))]) + datas = self.pool.get('ir.attachment').read(self.cr, self.uid, ids) if len(datas): # if there are several, pick first diff --git a/openerp/report/render/rml2pdf/trml2pdf.py b/openerp/report/render/rml2pdf/trml2pdf.py index a770a19ec27..0067bf300f2 100644 --- a/openerp/report/render/rml2pdf/trml2pdf.py +++ b/openerp/report/render/rml2pdf/trml2pdf.py @@ -447,14 +447,14 @@ class _rml_canvas(object): self._logger.debug("Image %s used", node.get('name')) s = StringIO(image_data) else: + newtext = node.text if self.localcontext: - res = utils._regex.findall(node.text) + res = utils._regex.findall(newtext) for key in res: - newtext = eval(key, {}, self.localcontext) - node.text = newtext or '' + newtext = eval(key, {}, self.localcontext) or '' image_data = None - if node.text: - image_data = base64.decodestring(node.text) + if newtext: + image_data = base64.decodestring(newtext) if image_data: s = StringIO(image_data) else: diff --git a/openerp/report/report_sxw.py b/openerp/report/report_sxw.py index 210a54760c4..98de86b01a8 100644 --- a/openerp/report/report_sxw.py +++ b/openerp/report/report_sxw.py @@ -68,6 +68,9 @@ rml2sxw = { 'para': 'p', } +def get_date_length(date_format=DT_FORMAT): + return len((datetime.now()).strftime(date_format)) + class _format(object): def set_value(self, cr, uid, name, object, field, lang_obj): self.object = object @@ -78,7 +81,7 @@ class _format(object): class _float_format(float, _format): def __init__(self,value): super(_float_format, self).__init__() - self.val = value + self.val = value or 0.0 def __str__(self): digits = 2 @@ -86,17 +89,17 @@ class _float_format(float, _format): digits = self._field.digits[1] if hasattr(self, 'lang_obj'): return self.lang_obj.format('%.' + str(digits) + 'f', self.name, True) - return self.val + return str(self.val) class _int_format(int, _format): def __init__(self,value): super(_int_format, self).__init__() - self.val = value and str(value) or str(0) + self.val = value or 0 def __str__(self): if hasattr(self,'lang_obj'): return self.lang_obj.format('%.d', self.name, True) - return self.val + return str(self.val) class _date_format(str, _format): def __init__(self,value): @@ -106,7 +109,7 @@ class _date_format(str, _format): def __str__(self): if self.val: if getattr(self,'name', None): - date = datetime.strptime(self.name, DT_FORMAT) + date = datetime.strptime(self.name[:get_date_length()], DT_FORMAT) return date.strftime(str(self.lang_obj.date_format)) return self.val @@ -264,7 +267,7 @@ class rml_parse(object): d = obj._field.digits[1] or DEFAULT_DIGITS return d - def formatLang(self, value, digits=None, date=False, date_time=False, grouping=True, monetary=False, dp=False): + def formatLang(self, value, digits=None, date=False, date_time=False, grouping=True, monetary=False, dp=False, currency_obj=False): """ Assuming 'Account' decimal.precision=3: formatLang(value) -> digits=2 (default) @@ -296,13 +299,19 @@ class rml_parse(object): date_format = date_format + " " + self.lang_dict['time_format'] parse_format = DHM_FORMAT if not isinstance(value, time.struct_time): - return time.strftime(date_format, time.strptime(value, parse_format)) + return time.strftime(date_format, time.strptime(value[:get_date_length(parse_format)], parse_format)) else: date = datetime(*value.timetuple()[:6]) return date.strftime(date_format) - return self.lang_dict['lang_obj'].format('%.' + str(digits) + 'f', value, grouping=grouping, monetary=monetary) + res = self.lang_dict['lang_obj'].format('%.' + str(digits) + 'f', value, grouping=grouping, monetary=monetary) + if currency_obj: + if currency_obj.position == 'after': + res='%s %s'%(res,currency_obj.symbol) + elif currency_obj and currency_obj.position == 'before': + res='%s %s'%(currency_obj.symbol, res) + return res def repeatIn(self, lst, name,nodes_parent=False): ret_lst = [] diff --git a/openerp/service/__init__.py b/openerp/service/__init__.py index b9ee98fcab0..1bb83dfd228 100644 --- a/openerp/service/__init__.py +++ b/openerp/service/__init__.py @@ -19,9 +19,21 @@ # ############################################################################## +import logging +import threading +import time + import http_server import netrpc_server import web_services +import websrv_lib + +import openerp.cron +import openerp.modules +import openerp.netsvc +import openerp.osv +import openerp.tools +import openerp.wsgi #.apidoc title: RPC Services @@ -34,5 +46,58 @@ import web_services low-level behavior of the wire. """ +def start_services(): + """ Start all services. + + Services include the different servers and cron threads. + + """ + # Instantiate local services (this is a legacy design). + openerp.osv.osv.start_object_proxy() + # Export (for RPC) services. + web_services.start_web_services() + + # Initialize the HTTP stack. + #http_server.init_servers() + #http_server.init_static_http() + netrpc_server.init_servers() + + # Start the main cron thread. + openerp.cron.start_master_thread() + + # Start the top-level servers threads (normally HTTP, HTTPS, and NETRPC). + openerp.netsvc.Server.startAll() + + # Start the WSGI server. + openerp.wsgi.start_server() + + +def stop_services(): + """ Stop all services. """ + # stop scheduling new jobs; we will have to wait for the jobs to complete below + openerp.cron.cancel_all() + + openerp.netsvc.Server.quitAll() + openerp.wsgi.stop_server() + config = openerp.tools.config + logger = logging.getLogger('server') + logger.info("Initiating shutdown") + logger.info("Hit CTRL-C again or send a second signal to force the shutdown.") + logging.shutdown() + + # Manually join() all threads before calling sys.exit() to allow a second signal + # to trigger _force_quit() in case some non-daemon threads won't exit cleanly. + # threading.Thread.join() should not mask signals (at least in python 2.5). + for thread in threading.enumerate(): + if thread != threading.currentThread() and not thread.isDaemon(): + while thread.isAlive(): + # Need a busyloop here as thread.join() masks signals + # and would prevent the forced shutdown. + thread.join(0.05) + time.sleep(0.05) + + openerp.modules.registry.RegistryManager.delete_all() + + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerp/service/http_server.py b/openerp/service/http_server.py index 61713e9f2dd..63bd991ee35 100644 --- a/openerp/service/http_server.py +++ b/openerp/service/http_server.py @@ -64,53 +64,6 @@ try: except ImportError: class SSLError(Exception): pass -class ThreadedHTTPServer(ConnThreadingMixIn, SimpleXMLRPCDispatcher, HTTPServer): - """ A threaded httpd server, with all the necessary functionality for us. - - It also inherits the xml-rpc dispatcher, so that some xml-rpc functions - will be available to the request handler - """ - encoding = None - allow_none = False - allow_reuse_address = 1 - _send_traceback_header = False - i = 0 - - def __init__(self, addr, requestHandler, proto='http', - logRequests=True, allow_none=False, encoding=None, bind_and_activate=True): - self.logRequests = logRequests - - SimpleXMLRPCDispatcher.__init__(self, allow_none, encoding) - HTTPServer.__init__(self, addr, requestHandler) - - self.numThreads = 0 - self.proto = proto - self.__threadno = 0 - - # [Bug #1222790] If possible, set close-on-exec flag; if a - # method spawns a subprocess, the subprocess shouldn't have - # the listening socket open. - if fcntl is not None and hasattr(fcntl, 'FD_CLOEXEC'): - flags = fcntl.fcntl(self.fileno(), fcntl.F_GETFD) - flags |= fcntl.FD_CLOEXEC - fcntl.fcntl(self.fileno(), fcntl.F_SETFD, flags) - - def handle_error(self, request, client_address): - """ Override the error handler - """ - - logging.getLogger("init").exception("Server error in request from %s:" % (client_address,)) - - def _mark_start(self, thread): - self.numThreads += 1 - - def _mark_end(self, thread): - self.numThreads -= 1 - - - def _get_next_name(self): - self.__threadno += 1 - return 'http-client-%d' % self.__threadno class HttpLogHandler: """ helper class for uniform log handling Please define self._logger at each class that is derived from this @@ -129,182 +82,6 @@ class HttpLogHandler: def log_request(self, code='-', size='-'): self._logger.log(netsvc.logging.DEBUG_RPC, '"%s" %s %s', self.requestline, str(code), str(size)) - -class MultiHandler2(HttpLogHandler, MultiHTTPHandler): - _logger = logging.getLogger('http') - - -class SecureMultiHandler2(HttpLogHandler, SecureMultiHTTPHandler): - _logger = logging.getLogger('https') - - def getcert_fnames(self): - tc = tools.config - fcert = tc.get('secure_cert_file', 'server.cert') - fkey = tc.get('secure_pkey_file', 'server.key') - return (fcert,fkey) - -class BaseHttpDaemon(threading.Thread, netsvc.Server): - _RealProto = '??' - - def __init__(self, interface, port, handler): - threading.Thread.__init__(self, name='%sDaemon-%d'%(self._RealProto, port)) - netsvc.Server.__init__(self) - self.__port = port - self.__interface = interface - - try: - self.server = ThreadedHTTPServer((interface, port), handler, proto=self._RealProto) - self.server.vdirs = [] - self.server.logRequests = True - self.server.timeout = self._busywait_timeout - logging.getLogger("web-services").info( - "starting %s service at %s port %d" % - (self._RealProto, interface or '0.0.0.0', port,)) - except Exception, e: - logging.getLogger("httpd").exception("Error occured when starting the server daemon.") - raise - - @property - def socket(self): - return self.server.socket - - def attach(self, path, gw): - pass - - def stop(self): - self.running = False - self._close_socket() - - def run(self): - self.running = True - while self.running: - try: - self.server.handle_request() - except (socket.error, select.error), e: - if self.running or e.args[0] != errno.EBADF: - raise - return True - - def stats(self): - res = "%sd: " % self._RealProto + ((self.running and "running") or "stopped") - if self.server: - res += ", %d threads" % (self.server.numThreads,) - return res - - def append_svc(self, service): - if not isinstance(service, HTTPDir): - raise Exception("Wrong class for http service") - - pos = len(self.server.vdirs) - lastpos = pos - while pos > 0: - pos -= 1 - if self.server.vdirs[pos].matches(service.path): - lastpos = pos - # we won't break here, but search all way to the top, to - # ensure there is no lesser entry that will shadow the one - # we are inserting. - self.server.vdirs.insert(lastpos, service) - - def list_services(self): - ret = [] - for svc in self.server.vdirs: - ret.append( ( svc.path, str(svc.handler)) ) - - return ret - - -class HttpDaemon(BaseHttpDaemon): - _RealProto = 'HTTP' - def __init__(self, interface, port): - super(HttpDaemon, self).__init__(interface, port, - handler=MultiHandler2) - -class HttpSDaemon(BaseHttpDaemon): - _RealProto = 'HTTPS' - def __init__(self, interface, port): - try: - super(HttpSDaemon, self).__init__(interface, port, - handler=SecureMultiHandler2) - except SSLError, e: - logging.getLogger('httpsd').exception( \ - "Can not load the certificate and/or the private key files") - raise - -httpd = None -httpsd = None - -def init_servers(): - global httpd, httpsd - if tools.config.get('xmlrpc'): - httpd = HttpDaemon(tools.config.get('xmlrpc_interface', ''), - int(tools.config.get('xmlrpc_port', 8069))) - - if tools.config.get('xmlrpcs'): - httpsd = HttpSDaemon(tools.config.get('xmlrpcs_interface', ''), - int(tools.config.get('xmlrpcs_port', 8071))) - -def reg_http_service(hts, secure_only = False): - """ Register some handler to httpd. - hts must be an HTTPDir - """ - global httpd, httpsd - - if httpd and not secure_only: - httpd.append_svc(hts) - - if httpsd: - httpsd.append_svc(hts) - - if (not httpd) and (not httpsd): - logging.getLogger('httpd').warning("No httpd available to register service %s" % hts.path) - return - -def list_http_services(protocol=None): - global httpd, httpsd - if httpd and (protocol == 'http' or protocol == None): - return httpd.list_services() - elif httpsd and (protocol == 'https' or protocol == None): - return httpsd.list_services() - else: - raise Exception("Incorrect protocol or no http services") - -import SimpleXMLRPCServer -class XMLRPCRequestHandler(netsvc.OpenERPDispatcher,FixSendError,HttpLogHandler,SimpleXMLRPCServer.SimpleXMLRPCRequestHandler): - rpc_paths = [] - protocol_version = 'HTTP/1.1' - _logger = logging.getLogger('xmlrpc') - - def _dispatch(self, method, params): - try: - service_name = self.path.split("/")[-1] - return self.dispatch(service_name, method, params) - except netsvc.OpenERPDispatcherException, e: - raise xmlrpclib.Fault(tools.exception_to_unicode(e.exception), e.traceback) - - def handle(self): - pass - - def finish(self): - pass - - def setup(self): - self.connection = dummyconn() - self.rpc_paths = map(lambda s: '/%s' % s, netsvc.ExportService._services.keys()) - - -def init_xmlrpc(): - if tools.config.get('xmlrpc', False): - # Example of http file serving: - # reg_http_service(HTTPDir('/test/',HTTPHandler)) - reg_http_service(HTTPDir('/xmlrpc/', XMLRPCRequestHandler)) - logging.getLogger("web-services").info("Registered XML-RPC over HTTP") - - if tools.config.get('xmlrpcs', False) \ - and not tools.config.get('xmlrpc', False): - # only register at the secure server - reg_http_service(HTTPDir('/xmlrpc/', XMLRPCRequestHandler), True) - logging.getLogger("web-services").info("Registered XML-RPC over HTTPS only") class StaticHTTPHandler(HttpLogHandler, FixSendError, HttpOptions, HTTPHandler): _logger = logging.getLogger('httpd') @@ -345,65 +122,21 @@ def init_static_http(): base_path = tools.config.get('static_http_url_prefix', '/') - reg_http_service(HTTPDir(base_path,StaticHTTPHandler)) + reg_http_service(base_path, StaticHTTPHandler) logging.getLogger("web-services").info("Registered HTTP dir %s for %s" % \ (document_root, base_path)) -class OerpAuthProxy(AuthProxy): - """ Require basic authentication.. +import security - This is a copy of the BasicAuthProxy, which however checks/caches the db - as well. - """ - def __init__(self,provider): - AuthProxy.__init__(self,provider) +class OpenERPAuthProvider(AuthProvider): + """ Require basic authentication.""" + def __init__(self,realm='OpenERP User'): + self.realm = realm self.auth_creds = {} self.auth_tries = 0 self.last_auth = None - def checkRequest(self,handler,path, db=False): - auth_str = handler.headers.get('Authorization',False) - try: - if not db: - db = handler.get_db_from_path(path) - except Exception: - if path.startswith('/'): - path = path[1:] - psp= path.split('/') - if len(psp)>1: - db = psp[0] - else: - #FIXME! - self.provider.log("Wrong path: %s, failing auth" %path) - raise AuthRejectedExc("Authorization failed. Wrong sub-path.") - if self.auth_creds.get(db): - return True - if auth_str and auth_str.startswith('Basic '): - auth_str=auth_str[len('Basic '):] - (user,passwd) = base64.decodestring(auth_str).split(':') - self.provider.log("Found user=\"%s\", passwd=\"***\" for db=\"%s\"" %(user,db)) - acd = self.provider.authenticate(db,user,passwd,handler.client_address) - if acd != False: - self.auth_creds[db] = acd - self.last_auth = db - return True - if self.auth_tries > 5: - self.provider.log("Failing authorization after 5 requests w/o password") - raise AuthRejectedExc("Authorization failed.") - self.auth_tries += 1 - raise AuthRequiredExc(atype='Basic', realm=self.provider.realm) - -import security -class OpenERPAuthProvider(AuthProvider): - def __init__(self,realm='OpenERP User'): - self.realm = realm - - def setupAuth(self, multi, handler): - if not multi.sec_realms.has_key(self.realm): - multi.sec_realms[self.realm] = OerpAuthProxy(self) - handler.auth_proxy = multi.sec_realms[self.realm] - def authenticate(self, db, user, passwd, client_address): try: uid = security.login(db,user,passwd) @@ -417,4 +150,36 @@ class OpenERPAuthProvider(AuthProvider): def log(self, msg, lvl=logging.INFO): logging.getLogger("auth").log(lvl,msg) + def checkRequest(self,handler,path, db=False): + auth_str = handler.headers.get('Authorization',False) + try: + if not db: + db = handler.get_db_from_path(path) + except Exception: + if path.startswith('/'): + path = path[1:] + psp= path.split('/') + if len(psp)>1: + db = psp[0] + else: + #FIXME! + self.log("Wrong path: %s, failing auth" %path) + raise AuthRejectedExc("Authorization failed. Wrong sub-path.") + if self.auth_creds.get(db): + return True + if auth_str and auth_str.startswith('Basic '): + auth_str=auth_str[len('Basic '):] + (user,passwd) = base64.decodestring(auth_str).split(':') + self.log("Found user=\"%s\", passwd=\"***\" for db=\"%s\"" %(user,db)) + acd = self.authenticate(db,user,passwd,handler.client_address) + if acd != False: + self.auth_creds[db] = acd + self.last_auth = db + return True + if self.auth_tries > 5: + self.log("Failing authorization after 5 requests w/o password") + raise AuthRejectedExc("Authorization failed.") + self.auth_tries += 1 + raise AuthRequiredExc(atype='Basic', realm=self.realm) + #eof diff --git a/openerp/service/netrpc_server.py b/openerp/service/netrpc_server.py index 70855a018e5..adebca63c7f 100644 --- a/openerp/service/netrpc_server.py +++ b/openerp/service/netrpc_server.py @@ -36,7 +36,7 @@ import openerp.netsvc as netsvc import openerp.tiny_socket as tiny_socket import openerp.tools as tools -class TinySocketClientThread(threading.Thread, netsvc.OpenERPDispatcher): +class TinySocketClientThread(threading.Thread): def __init__(self, sock, threads): spn = sock and sock.getpeername() spn = 'netrpc-client-%s:%s' % spn[0:2] @@ -59,26 +59,19 @@ class TinySocketClientThread(threading.Thread, netsvc.OpenERPDispatcher): while self.running: try: msg = ts.myreceive() - result = self.dispatch(msg[0], msg[1], msg[2:]) + auth = getattr(self, 'auth_provider', None) + result = netsvc.dispatch_rpc(msg[0], msg[1], msg[2:], auth) ts.mysend(result) except socket.timeout: #terminate this channel because other endpoint is gone break - except netsvc.OpenERPDispatcherException, e: - try: - new_e = Exception(tools.exception_to_unicode(e.exception)) # avoid problems of pickeling - logging.getLogger('web-services').debug("netrpc: rpc-dispatching exception", exc_info=True) - ts.mysend(new_e, exception=True, traceback=e.traceback) - except Exception: - #terminate this channel if we can't properly send back the error - logging.getLogger('web-services').exception("netrpc: cannot deliver exception message to client") - break except Exception, e: try: + new_e = Exception(tools.exception_to_unicode(e)) # avoid problems of pickeling tb = getattr(e, 'traceback', sys.exc_info()) tb_s = "".join(traceback.format_exception(*tb)) logging.getLogger('web-services').debug("netrpc: communication-level exception", exc_info=True) - ts.mysend(e, exception=True, traceback=tb_s) + ts.mysend(new_e, exception=True, traceback=tb_s) break except Exception, ex: #terminate this channel if we can't properly send back the error @@ -107,7 +100,7 @@ class TinySocketServerThread(threading.Thread,netsvc.Server): self.socket.listen(5) self.threads = [] netsvc.Logger().notifyChannel("web-services", netsvc.LOG_INFO, - "starting NET-RPC service at %s port %d" % (interface or '0.0.0.0', port,)) + "starting NET-RPC service on %s:%s" % (interface or '0.0.0.0', port,)) def run(self): try: diff --git a/openerp/service/security.py b/openerp/service/security.py index 86c381b683f..ff140ad261b 100644 --- a/openerp/service/security.py +++ b/openerp/service/security.py @@ -19,18 +19,12 @@ # ############################################################################## +import openerp.exceptions import openerp.pooler as pooler import openerp.tools as tools #.apidoc title: Authentication helpers -class ExceptionNoTb(Exception): - """ When rejecting a password, hide the traceback - """ - def __init__(self, msg): - super(ExceptionNoTb, self).__init__(msg) - self.traceback = ('','','') - def login(db, login, password): pool = pooler.get_pool(db) user_obj = pool.get('res.users') @@ -40,7 +34,7 @@ def check_super(passwd): if passwd == tools.config['admin_passwd']: return True else: - raise ExceptionNoTb('AccessDenied: Invalid super administrator password.') + raise openerp.exceptions.AccessDenied() def check(db, uid, passwd): pool = pooler.get_pool(db) diff --git a/openerp/service/web_services.py b/openerp/service/web_services.py index 58614922dfa..7b14768fc9e 100644 --- a/openerp/service/web_services.py +++ b/openerp/service/web_services.py @@ -38,6 +38,7 @@ import openerp.release as release import openerp.sql_db as sql_db import openerp.tools as tools import openerp.modules +import openerp.exceptions class edi(netsvc.ExportService): def exp_get_edi_document(self, edi_token, db_name): @@ -149,17 +150,17 @@ def _initialize_db(serv, id, db_name, demo, lang, user_password): class db(netsvc.ExportService): def __init__(self, name="db"): netsvc.ExportService.__init__(self, name) - self.joinGroup("web-services") self.actions = {} self.id = 0 self.id_protect = threading.Semaphore() self._pg_psw_env_var_is_set = False # on win32, pg_dump need the PGPASSWORD env var - def dispatch(self, method, auth, params): + def dispatch(self, method, params): if method in [ 'create', 'get_progress', 'drop', 'dump', 'restore', 'rename', - 'change_admin_password', 'migrate_databases' ]: + 'change_admin_password', 'migrate_databases', + 'create_database' ]: passwd = params[0] params = params[1:] security.check_super(passwd) @@ -172,8 +173,6 @@ class db(netsvc.ExportService): fn = getattr(self, 'exp_'+method) return fn(*params) - def new_dispatch(self,method,auth,params): - pass def _create_empty_database(self, name): db = sql_db.db_connect('template1') cr = db.cursor() @@ -200,6 +199,20 @@ class db(netsvc.ExportService): self.actions[id]['thread'] = create_thread return id + def exp_create_database(self, db_name, demo, lang, user_password='admin'): + """ Similar to exp_create but blocking.""" + self.id_protect.acquire() + self.id += 1 + id = self.id + self.id_protect.release() + + self.actions[id] = {'clean': False} + + logging.getLogger('db.create').info('CREATE DATABASE %s', db_name.lower()) + self._create_empty_database(db_name) + _initialize_db(self, id, db_name, demo, lang, user_password) + return True + def exp_get_progress(self, id): if self.actions[id]['thread'].isAlive(): # return openerp.modules.init_progress[db_name] @@ -211,14 +224,13 @@ class db(netsvc.ExportService): self.actions.pop(id) return (1.0, users) else: - e = self.actions[id]['exception'] + e = self.actions[id]['exception'] # TODO this seems wrong: actions[id]['traceback'] is set, but not 'exception'. self.actions.pop(id) raise Exception, e def exp_drop(self, db_name): + openerp.modules.registry.RegistryManager.delete(db_name) sql_db.close_db(db_name) - openerp.modules.registry.RegistryManager.clear_caches(db_name) - openerp.netsvc.Agent.cancel(db_name) logger = netsvc.Logger() db = sql_db.db_connect('template1') @@ -320,9 +332,8 @@ class db(netsvc.ExportService): return True def exp_rename(self, old_name, new_name): + openerp.modules.registry.RegistryManager.delete(old_name) sql_db.close_db(old_name) - openerp.modules.registry.RegistryManager.clear_caches(old_name) - openerp.netsvc.Agent.cancel(old_name) logger = netsvc.Logger() db = sql_db.db_connect('template1') @@ -352,7 +363,7 @@ class db(netsvc.ExportService): def exp_list(self, document=False): if not tools.config['list_db'] and not document: - raise Exception('AccessDenied') + raise openerp.exceptions.AccessDenied() db = sql_db.db_connect('template1') cr = db.cursor() @@ -404,9 +415,9 @@ class db(netsvc.ExportService): tools.config['update']['base'] = True pooler.restart_pool(db, force_demo=False, update_module=True) except except_orm, inst: - self.abortResponse(1, inst.name, 'warning', inst.value) + netsvc.abort_response(1, inst.name, 'warning', inst.value) except except_osv, inst: - self.abortResponse(1, inst.name, inst.exc_type, inst.value) + netsvc.abort_response(1, inst.name, 'warning', inst.value) except Exception: import traceback tb_s = reduce(lambda x, y: x+y, traceback.format_exception( sys.exc_type, sys.exc_value, sys.exc_traceback)) @@ -414,39 +425,18 @@ class db(netsvc.ExportService): raise return True -class _ObjectService(netsvc.ExportService): - "A common base class for those who have fn(db, uid, password,...) " - - def common_dispatch(self, method, auth, params): - (db, uid, passwd ) = params[0:3] - params = params[3:] - security.check(db,uid,passwd) - cr = pooler.get_db(db).cursor() - fn = getattr(self, 'exp_'+method) - res = fn(cr, uid, *params) - cr.commit() - cr.close() - return res - -class common(_ObjectService): +class common(netsvc.ExportService): def __init__(self,name="common"): - _ObjectService.__init__(self,name) - self.joinGroup("web-services") + netsvc.ExportService.__init__(self,name) - def dispatch(self, method, auth, params): + def dispatch(self, method, params): logger = netsvc.Logger() if method == 'login': - # At this old dispatcher, we do NOT update the auth proxy res = security.login(params[0], params[1], params[2]) msg = res and 'successful login' or 'bad login or password' # TODO log the client ip address.. logger.notifyChannel("web-service", netsvc.LOG_INFO, "%s from '%s' using database '%s'" % (msg, params[1], params[0].lower())) return res or False - elif method == 'logout': - if auth: - auth.logout(params[1]) - logger.notifyChannel("web-service", netsvc.LOG_INFO,'Logout %s from database %s'%(login,db)) - return True elif method in ['about', 'timezone_get', 'get_server_environment', 'login_message','get_stats', 'check_connectivity', 'list_http_services']: @@ -461,10 +451,6 @@ class common(_ObjectService): fn = getattr(self, 'exp_'+method) return fn(*params) - - def new_dispatch(self,method,auth,params): - pass - def exp_about(self, extended=False): """Return information about the OpenERP Server. @@ -498,7 +484,7 @@ GNU Public Licence. return rc.get_available_updates(rc.id, openerp.modules.get_modules_with_version()) except tm.RemoteContractException, e: - self.abortResponse(1, 'Migration Error', 'warning', str(e)) + netsvc.abort_response(1, 'Migration Error', 'warning', str(e)) def exp_get_migration_scripts(self, contract_id, contract_password): @@ -566,7 +552,7 @@ GNU Public Licence. return True except tm.RemoteContractException, e: - self.abortResponse(1, 'Migration Error', 'warning', str(e)) + netsvc.abort_response(1, 'Migration Error', 'warning', str(e)) except Exception, e: import traceback tb_s = reduce(lambda x, y: x+y, traceback.format_exception( sys.exc_type, sys.exc_value, sys.exc_traceback)) @@ -630,9 +616,8 @@ GNU Public Licence. class objects_proxy(netsvc.ExportService): def __init__(self, name="object"): netsvc.ExportService.__init__(self,name) - self.joinGroup('web-services') - def dispatch(self, method, auth, params): + def dispatch(self, method, params): (db, uid, passwd ) = params[0:3] params = params[3:] if method == 'obj_list': @@ -640,16 +625,12 @@ class objects_proxy(netsvc.ExportService): if method not in ['execute','exec_workflow']: raise NameError("Method not available %s" % method) security.check(db,uid,passwd) - ls = netsvc.LocalService('object_proxy') - fn = getattr(ls, method) + assert openerp.osv.osv.service, "The object_proxy class must be started with start_object_proxy." + fn = getattr(openerp.osv.osv.service, method) res = fn(db, uid, *params) return res - def new_dispatch(self,method,auth,params): - pass - - # # Wizard ID: 1 # - None = end of wizard @@ -664,13 +645,12 @@ class objects_proxy(netsvc.ExportService): class wizard(netsvc.ExportService): def __init__(self, name='wizard'): netsvc.ExportService.__init__(self,name) - self.joinGroup('web-services') self.id = 0 self.wiz_datas = {} self.wiz_name = {} self.wiz_uid = {} - def dispatch(self, method, auth, params): + def dispatch(self, method, params): (db, uid, passwd ) = params[0:3] params = params[3:] if method not in ['execute','create']: @@ -680,9 +660,6 @@ class wizard(netsvc.ExportService): res = fn(db, uid, *params) return res - def new_dispatch(self,method,auth,params): - pass - def _execute(self, db, uid, wiz_id, datas, action, context): self.wiz_datas[wiz_id].update(datas) wiz = netsvc.LocalService('wizard.'+self.wiz_name[wiz_id]) @@ -706,9 +683,9 @@ class wizard(netsvc.ExportService): if self.wiz_uid[wiz_id] == uid: return self._execute(db, uid, wiz_id, datas, action, context) else: - raise Exception, 'AccessDenied' + raise openerp.exceptions.AccessDenied() else: - raise Exception, 'WizardNotFound' + raise openerp.exceptions.Warning('Wizard not found.') # # TODO: set a maximum report number per user to avoid DOS attacks @@ -717,33 +694,64 @@ class wizard(netsvc.ExportService): # False -> True # -class ExceptionWithTraceback(Exception): - def __init__(self, msg, tb): - self.message = msg - self.traceback = tb - self.args = (msg, tb) - class report_spool(netsvc.ExportService): def __init__(self, name='report'): netsvc.ExportService.__init__(self, name) - self.joinGroup('web-services') self._reports = {} self.id = 0 self.id_protect = threading.Semaphore() - def dispatch(self, method, auth, params): + def dispatch(self, method, params): (db, uid, passwd ) = params[0:3] params = params[3:] - if method not in ['report','report_get']: + if method not in ['report', 'report_get', 'render_report']: raise KeyError("Method not supported %s" % method) security.check(db,uid,passwd) fn = getattr(self, 'exp_' + method) res = fn(db, uid, *params) return res + def exp_render_report(self, db, uid, object, ids, datas=None, context=None): + if not datas: + datas={} + if not context: + context={} - def new_dispatch(self,method,auth,params): - pass + self.id_protect.acquire() + self.id += 1 + id = self.id + self.id_protect.release() + + self._reports[id] = {'uid': uid, 'result': False, 'state': False, 'exception': None} + + cr = pooler.get_db(db).cursor() + import traceback + import sys + try: + obj = netsvc.LocalService('report.'+object) + (result, format) = obj.create(cr, uid, ids, datas, context) + if not result: + tb = sys.exc_info() + self._reports[id]['exception'] = openerp.exceptions.DeferredException('RML is not available at specified location or not enough data to print!', tb) + self._reports[id]['result'] = result + self._reports[id]['format'] = format + self._reports[id]['state'] = True + except Exception, exception: + + tb = sys.exc_info() + tb_s = "".join(traceback.format_exception(*tb)) + logger = netsvc.Logger() + logger.notifyChannel('web-services', netsvc.LOG_ERROR, + 'Exception: %s\n%s' % (str(exception), tb_s)) + if hasattr(exception, 'name') and hasattr(exception, 'value'): + self._reports[id]['exception'] = openerp.exceptions.DeferredException(tools.ustr(exception.name), tools.ustr(exception.value)) + else: + self._reports[id]['exception'] = openerp.exceptions.DeferredException(tools.exception_to_unicode(exception), tb) + self._reports[id]['state'] = True + cr.commit() + cr.close() + + return self._check_report(id) def exp_report(self, db, uid, object, ids, datas=None, context=None): if not datas: @@ -767,7 +775,7 @@ class report_spool(netsvc.ExportService): (result, format) = obj.create(cr, uid, ids, datas, context) if not result: tb = sys.exc_info() - self._reports[id]['exception'] = ExceptionWithTraceback('RML is not available at specified location or not enough data to print!', tb) + self._reports[id]['exception'] = openerp.exceptions.DeferredException('RML is not available at specified location or not enough data to print!', tb) self._reports[id]['result'] = result self._reports[id]['format'] = format self._reports[id]['state'] = True @@ -779,9 +787,9 @@ class report_spool(netsvc.ExportService): logger.notifyChannel('web-services', netsvc.LOG_ERROR, 'Exception: %s\n%s' % (str(exception), tb_s)) if hasattr(exception, 'name') and hasattr(exception, 'value'): - self._reports[id]['exception'] = ExceptionWithTraceback(tools.ustr(exception.name), tools.ustr(exception.value)) + self._reports[id]['exception'] = openerp.exceptions.DeferredException(tools.ustr(exception.name), tools.ustr(exception.value)) else: - self._reports[id]['exception'] = ExceptionWithTraceback(tools.exception_to_unicode(exception), tb) + self._reports[id]['exception'] = openerp.exceptions.DeferredException(tools.exception_to_unicode(exception), tb) self._reports[id]['state'] = True cr.commit() cr.close() @@ -794,7 +802,7 @@ class report_spool(netsvc.ExportService): result = self._reports[report_id] exc = result['exception'] if exc: - self.abortResponse(exc, exc.message, 'warning', exc.traceback) + netsvc.abort_response(exc, exc.message, 'warning', exc.traceback) res = {'state': result['state']} if res['state']: if tools.config['reportgz']: diff --git a/openerp/service/websrv_lib.py b/openerp/service/websrv_lib.py index 2e098169bae..3df441458fd 100644 --- a/openerp/service/websrv_lib.py +++ b/openerp/service/websrv_lib.py @@ -52,61 +52,17 @@ class AuthProvider: def __init__(self,realm): self.realm = realm - def setupAuth(self, multi,handler): - """ Attach an AuthProxy object to handler - """ - pass - def authenticate(self, user, passwd, client_address): return False def log(self, msg): print msg -class BasicAuthProvider(AuthProvider): - def setupAuth(self, multi, handler): - if not multi.sec_realms.has_key(self.realm): - multi.sec_realms[self.realm] = BasicAuthProxy(self) - - -class AuthProxy: - """ This class will hold authentication information for a handler, - i.e. a connection - """ - def __init__(self, provider): - self.provider = provider - def checkRequest(self,handler,path = '/'): """ Check if we are allowed to process that request """ pass -class BasicAuthProxy(AuthProxy): - """ Require basic authentication.. - """ - def __init__(self,provider): - AuthProxy.__init__(self,provider) - self.auth_creds = None - self.auth_tries = 0 - - def checkRequest(self,handler,path = '/'): - if self.auth_creds: - return True - auth_str = handler.headers.get('Authorization',False) - if auth_str and auth_str.startswith('Basic '): - auth_str=auth_str[len('Basic '):] - (user,passwd) = base64.decodestring(auth_str).split(':') - self.provider.log("Found user=\"%s\", passwd=\"%s\"" %(user,passwd)) - self.auth_creds = self.provider.authenticate(user,passwd,handler.client_address) - if self.auth_creds: - return True - if self.auth_tries > 5: - self.provider.log("Failing authorization after 5 requests w/o password") - raise AuthRejectedExc("Authorization failed.") - self.auth_tries += 1 - raise AuthRequiredExc(atype = 'Basic', realm=self.provider.realm) - - class HTTPHandler(SimpleHTTPRequestHandler): def __init__(self,request, client_address, server): SimpleHTTPRequestHandler.__init__(self,request,client_address,server) @@ -125,13 +81,17 @@ class HTTPHandler(SimpleHTTPRequestHandler): def setup(self): pass +# A list of HTTPDir. +handlers = [] + class HTTPDir: """ A dispatcher class, like a virtual folder in httpd """ - def __init__(self,path,handler, auth_provider = None): + def __init__(self, path, handler, auth_provider=None, secure_only=False): self.path = path self.handler = handler self.auth_provider = auth_provider + self.secure_only = secure_only def matches(self, request): """ Test if some request matches us. If so, return @@ -140,6 +100,48 @@ class HTTPDir: return self.path return False + def instanciate_handler(self, request, client_address, server): + handler = self.handler(noconnection(request), client_address, server) + if self.auth_provider: + handler.auth_provider = self.auth_provider() + return handler + +def reg_http_service(path, handler, auth_provider=None, secure_only=False): + """ Register a HTTP handler at a given path. + + The auth_provider will be instanciated and set on the handler instances. + """ + global handlers + service = HTTPDir(path, handler, auth_provider, secure_only) + pos = len(handlers) + lastpos = pos + while pos > 0: + pos -= 1 + if handlers[pos].matches(service.path): + lastpos = pos + # we won't break here, but search all way to the top, to + # ensure there is no lesser entry that will shadow the one + # we are inserting. + handlers.insert(lastpos, service) + +def list_http_services(protocol=None): + global handlers + ret = [] + for svc in handlers: + if protocol is None or protocol == 'http' or svc.secure_only: + ret.append((svc.path, str(svc.handler))) + + return ret + +def find_http_service(path, secure=False): + global handlers + for vdir in handlers: + p = vdir.matches(path) + if p == False or (vdir.secure_only and not secure): + continue + return vdir + return None + class noconnection(object): """ a class to use instead of the real connection """ @@ -230,312 +232,3 @@ class HttpOptions: """ return opts -class MultiHTTPHandler(FixSendError, HttpOptions, BaseHTTPRequestHandler): - """ this is a multiple handler, that will dispatch each request - to a nested handler, iff it matches - - The handler will also have *one* dict of authentication proxies, - groupped by their realm. - """ - - protocol_version = "HTTP/1.1" - default_request_version = "HTTP/0.9" # compatibility with py2.5 - - auth_required_msg = """ Authorization required - You must authenticate to use this service\r\r""" - - def __init__(self, request, client_address, server): - self.in_handlers = {} - self.sec_realms = {} - SocketServer.StreamRequestHandler.__init__(self,request,client_address,server) - self.log_message("MultiHttpHandler init for %s" %(str(client_address))) - - def _handle_one_foreign(self,fore, path, auth_provider): - """ This method overrides the handle_one_request for *children* - handlers. It is required, since the first line should not be - read again.. - - """ - fore.raw_requestline = "%s %s %s\n" % (self.command, path, self.version) - if not fore.parse_request(): # An error code has been sent, just exit - return - if fore.headers.status: - self.log_error("Parse error at headers: %s", fore.headers.status) - self.close_connection = 1 - self.send_error(400,"Parse error at HTTP headers") - return - - self.request_version = fore.request_version - if auth_provider and auth_provider.realm: - try: - self.sec_realms[auth_provider.realm].checkRequest(fore,path) - except AuthRequiredExc,ae: - # Darwin 9.x.x webdav clients will report "HTTP/1.0" to us, while they support (and need) the - # authorisation features of HTTP/1.1 - if self.request_version != 'HTTP/1.1' and ('Darwin/9.' not in fore.headers.get('User-Agent', '')): - self.log_error("Cannot require auth at %s", self.request_version) - self.send_error(403) - return - self._get_ignore_body(fore) # consume any body that came, not loose sync with input - self.send_response(401,'Authorization required') - self.send_header('WWW-Authenticate','%s realm="%s"' % (ae.atype,ae.realm)) - self.send_header('Connection', 'keep-alive') - self.send_header('Content-Type','text/html') - self.send_header('Content-Length',len(self.auth_required_msg)) - self.end_headers() - self.wfile.write(self.auth_required_msg) - return - except AuthRejectedExc,e: - self.log_error("Rejected auth: %s" % e.args[0]) - self.send_error(403,e.args[0]) - self.close_connection = 1 - return - mname = 'do_' + fore.command - if not hasattr(fore, mname): - if fore.command == 'OPTIONS': - self.do_OPTIONS() - return - self.send_error(501, "Unsupported method (%r)" % fore.command) - return - fore.close_connection = 0 - method = getattr(fore, mname) - try: - method() - except (AuthRejectedExc, AuthRequiredExc): - raise - except Exception, e: - if hasattr(self, 'log_exception'): - self.log_exception("Could not run %s", mname) - else: - self.log_error("Could not run %s: %s", mname, e) - self.send_error(500, "Internal error") - # may not work if method has already sent data - fore.close_connection = 1 - self.close_connection = 1 - if hasattr(fore, '_flush'): - fore._flush() - return - - if fore.close_connection: - # print "Closing connection because of handler" - self.close_connection = fore.close_connection - if hasattr(fore, '_flush'): - fore._flush() - - - def parse_rawline(self): - """Parse a request (internal). - - The request should be stored in self.raw_requestline; the results - are in self.command, self.path, self.request_version and - self.headers. - - Return True for success, False for failure; on failure, an - error is sent back. - - """ - self.command = None # set in case of error on the first line - self.request_version = version = self.default_request_version - self.close_connection = 1 - requestline = self.raw_requestline - if requestline[-2:] == '\r\n': - requestline = requestline[:-2] - elif requestline[-1:] == '\n': - requestline = requestline[:-1] - self.requestline = requestline - words = requestline.split() - if len(words) == 3: - [command, path, version] = words - if version[:5] != 'HTTP/': - self.send_error(400, "Bad request version (%r)" % version) - return False - try: - base_version_number = version.split('/', 1)[1] - version_number = base_version_number.split(".") - # RFC 2145 section 3.1 says there can be only one "." and - # - major and minor numbers MUST be treated as - # separate integers; - # - HTTP/2.4 is a lower version than HTTP/2.13, which in - # turn is lower than HTTP/12.3; - # - Leading zeros MUST be ignored by recipients. - if len(version_number) != 2: - raise ValueError - version_number = int(version_number[0]), int(version_number[1]) - except (ValueError, IndexError): - self.send_error(400, "Bad request version (%r)" % version) - return False - if version_number >= (1, 1): - self.close_connection = 0 - if version_number >= (2, 0): - self.send_error(505, - "Invalid HTTP Version (%s)" % base_version_number) - return False - elif len(words) == 2: - [command, path] = words - self.close_connection = 1 - if command != 'GET': - self.log_error("Junk http request: %s", self.raw_requestline) - self.send_error(400, - "Bad HTTP/0.9 request type (%r)" % command) - return False - elif not words: - return False - else: - #self.send_error(400, "Bad request syntax (%r)" % requestline) - return False - self.request_version = version - self.command, self.path, self.version = command, path, version - return True - - def handle_one_request(self): - """Handle a single HTTP request. - Dispatch to the correct handler. - """ - self.request.setblocking(True) - self.raw_requestline = self.rfile.readline() - if not self.raw_requestline: - self.close_connection = 1 - # self.log_message("no requestline, connection closed?") - return - if not self.parse_rawline(): - self.log_message("Could not parse rawline.") - return - # self.parse_request(): # Do NOT parse here. the first line should be the only - - if self.path == '*' and self.command == 'OPTIONS': - # special handling of path='*', must not use any vdir at all. - if not self.parse_request(): - return - self.do_OPTIONS() - return - - for vdir in self.server.vdirs: - p = vdir.matches(self.path) - if p == False: - continue - npath = self.path[len(p):] - if not npath.startswith('/'): - npath = '/' + npath - - if not self.in_handlers.has_key(p): - self.in_handlers[p] = vdir.handler(noconnection(self.request),self.client_address,self.server) - if vdir.auth_provider: - vdir.auth_provider.setupAuth(self, self.in_handlers[p]) - hnd = self.in_handlers[p] - hnd.rfile = self.rfile - hnd.wfile = self.wfile - self.rlpath = self.raw_requestline - try: - self._handle_one_foreign(hnd,npath, vdir.auth_provider) - except IOError, e: - if e.errno == errno.EPIPE: - self.log_message("Could not complete request %s," \ - "client closed connection", self.rlpath.rstrip()) - else: - raise - return - # if no match: - self.send_error(404, "Path not found: %s" % self.path) - return - - def _get_ignore_body(self,fore): - if not fore.headers.has_key("content-length"): - return - max_chunk_size = 10*1024*1024 - size_remaining = int(fore.headers["content-length"]) - got = '' - while size_remaining: - chunk_size = min(size_remaining, max_chunk_size) - got = fore.rfile.read(chunk_size) - size_remaining -= len(got) - - -class SecureMultiHTTPHandler(MultiHTTPHandler): - def getcert_fnames(self): - """ Return a pair with the filenames of ssl cert,key - - Override this to direct to other filenames - """ - return ('server.cert','server.key') - - def setup(self): - import ssl - certfile, keyfile = self.getcert_fnames() - try: - self.connection = ssl.wrap_socket(self.request, - server_side=True, - certfile=certfile, - keyfile=keyfile, - ssl_version=ssl.PROTOCOL_SSLv23) - self.rfile = self.connection.makefile('rb', self.rbufsize) - self.wfile = self.connection.makefile('wb', self.wbufsize) - self.log_message("Secure %s connection from %s",self.connection.cipher(),self.client_address) - except Exception: - self.request.shutdown(socket.SHUT_RDWR) - raise - - def finish(self): - # With ssl connections, closing the filehandlers alone may not - # work because of ref counting. We explicitly tell the socket - # to shutdown. - MultiHTTPHandler.finish(self) - try: - self.connection.shutdown(socket.SHUT_RDWR) - except Exception: - pass - -import threading -class ConnThreadingMixIn: - """Mix-in class to handle each _connection_ in a new thread. - - This is necessary for persistent connections, where multiple - requests should be handled synchronously at each connection, but - multiple connections can run in parallel. - """ - - # Decides how threads will act upon termination of the - # main process - daemon_threads = False - - def _get_next_name(self): - return None - - def _handle_request_noblock(self): - """Start a new thread to process the request.""" - if not threading: # happens while quitting python - return - t = threading.Thread(name=self._get_next_name(), target=self._handle_request2) - if self.daemon_threads: - t.setDaemon (1) - t.start() - - def _mark_start(self, thread): - """ Mark the start of a request thread """ - pass - - def _mark_end(self, thread): - """ Mark the end of a request thread """ - pass - - def _handle_request2(self): - """Handle one request, without blocking. - - I assume that select.select has returned that the socket is - readable before this function was called, so there should be - no risk of blocking in get_request(). - """ - try: - self._mark_start(threading.currentThread()) - request, client_address = self.get_request() - if self.verify_request(request, client_address): - try: - self.process_request(request, client_address) - except Exception: - self.handle_error(request, client_address) - self.close_request(request) - except socket.error: - return - finally: - self._mark_end(threading.currentThread()) - -#eof diff --git a/openerp/sql_db.py b/openerp/sql_db.py index 79606b9101c..ab92d7cc21d 100644 --- a/openerp/sql_db.py +++ b/openerp/sql_db.py @@ -183,6 +183,8 @@ class Cursor(object): self.__caller = False self.__closer = False + self._default_log_exceptions = True + def __del__(self): if not self.__closed: # Oops. 'self' has not been closed explicitly. @@ -199,7 +201,7 @@ class Cursor(object): self._close(True) @check - def execute(self, query, params=None, log_exceptions=True): + def execute(self, query, params=None, log_exceptions=None): if '%d' in query or '%f' in query: self.__logger.warn(query) self.__logger.warn("SQL queries cannot contain %d or %f anymore. " @@ -212,11 +214,11 @@ class Cursor(object): params = params or None res = self._obj.execute(query, params) except psycopg2.ProgrammingError, pe: - if log_exceptions: + if (self._default_log_exceptions if log_exceptions is None else log_exceptions): self.__logger.error("Programming error: %s, in query %s", pe, query) raise except Exception: - if log_exceptions: + if (self._default_log_exceptions if log_exceptions is None else log_exceptions): self.__logger.exception("bad query: %s", self._obj.query or query) raise @@ -502,7 +504,7 @@ def db_connect(db_name): return Connection(_Pool, db_name) def close_db(db_name): - """ You might want to call openerp.netsvc.Agent.cancel(db_name) along this function.""" + """ You might want to call openerp.modules.registry.RegistryManager.delete(db_name) along this function.""" _Pool.close_all(dsn(db_name)) ct = currentThread() if hasattr(ct, 'dbname'): diff --git a/openerp/tools/config.py b/openerp/tools/config.py index 18f40e0011f..ce6745af7d4 100644 --- a/openerp/tools/config.py +++ b/openerp/tools/config.py @@ -24,6 +24,7 @@ import optparse import os import sys import openerp +import openerp.conf import openerp.loglevels as loglevels import logging import openerp.release as release @@ -101,8 +102,10 @@ class configmanager(object): group.add_option("-P", "--import-partial", dest="import_partial", my_default='', help="Use this for big data importation, if it crashes you will be able to continue at the current state. Provide a filename to store intermediate importation states.") group.add_option("--pidfile", dest="pidfile", help="file where the server pid will be stored") + group.add_option("--load", dest="server_wide_modules", help="Comma-separated list of server-wide modules") parser.add_option_group(group) + # XML-RPC / HTTP group = optparse.OptionGroup(parser, "XML-RPC Configuration") group.add_option("--xmlrpc-interface", dest="xmlrpc_interface", my_default='', help="Specify the TCP IP address for the XML-RPC protocol. The empty string binds to all interfaces.") @@ -112,6 +115,7 @@ class configmanager(object): help="disable the XML-RPC protocol") parser.add_option_group(group) + # XML-RPC / HTTPS title = "XML-RPC Secure Configuration" if not self.has_ssl: title += " (disabled as ssl is unavailable)" @@ -139,6 +143,13 @@ class configmanager(object): help="disable the NETRPC protocol") parser.add_option_group(group) + # WEB + # TODO move to web addons after MetaOption merge + group = optparse.OptionGroup(parser, "Web interface Configuration") + group.add_option("--db-filter", dest="dbfilter", default='.*', + help="Filter listed database", metavar="REGEXP") + parser.add_option_group(group) + # Static HTTP group = optparse.OptionGroup(parser, "Static HTTP service") group.add_option("--static-http-enable", dest="static_http_enable", action="store_true", my_default=False, help="enable static HTTP service for serving plain HTML files") @@ -250,6 +261,12 @@ class configmanager(object): "osv_memory tables. This is a decimal value expressed in hours, " "and the default is 1 hour.", type="float") + group.add_option("--max-cron-threads", dest="max_cron_threads", my_default=4, + help="Maximum number of threads processing concurrently cron jobs.", + type="int") + group.add_option("--unaccent", dest="unaccent", my_default=False, action="store_true", + help="Use the unaccent function provided by the database when available.") + parser.add_option_group(group) # Copy all optparse options (i.e. MyOption) into self.options. @@ -258,9 +275,26 @@ class configmanager(object): self.options[option.dest] = option.my_default self.casts[option.dest] = option - self.parse_config() + self.parse_config(None, False) - def parse_config(self, args=None): + def parse_config(self, args=None, complete=True): + """ Parse the configuration file (if any) and the command-line + arguments. + + This method initializes openerp.tools.config and openerp.conf (the + former should be removed in the furture) with library-wide + configuration values. + + This method must be called before proper usage of this library can be + made. + + Typical usage of this method: + + openerp.tools.config.parse_config(sys.argv[1:]) + + :param complete: this is a hack used in __init__(), leave it to True. + + """ if args is None: args = [] opt, args = self.parser.parse_args(args) @@ -317,8 +351,8 @@ class configmanager(object): 'netrpc_interface', 'netrpc_port', 'db_maxconn', 'import_partial', 'addons_path', 'netrpc', 'xmlrpc', 'syslog', 'without_demo', 'timezone', 'xmlrpcs_interface', 'xmlrpcs_port', 'xmlrpcs', - 'secure_cert_file', 'secure_pkey_file', - 'static_http_enable', 'static_http_document_root', 'static_http_url_prefix' + 'static_http_enable', 'static_http_document_root', 'static_http_url_prefix', + 'secure_cert_file', 'secure_pkey_file', 'dbfilter' ] for arg in keys: @@ -335,7 +369,7 @@ class configmanager(object): 'stop_after_init', 'logrotate', 'without_demo', 'netrpc', 'xmlrpc', 'syslog', 'list_db', 'xmlrpcs', 'test_file', 'test_disable', 'test_commit', 'test_report_directory', - 'osv_memory_count_limit', 'osv_memory_age_limit', + 'osv_memory_count_limit', 'osv_memory_age_limit', 'max_cron_threads', 'unaccent', ] for arg in keys: @@ -417,6 +451,19 @@ class configmanager(object): if opt.save: self.save() + openerp.conf.max_cron_threads = self.options['max_cron_threads'] + + openerp.conf.addons_paths = self.options['addons_path'].split(',') + openerp.conf.server_wide_modules = \ + map(lambda m: m.strip(), opt.server_wide_modules.split(',')) if \ + opt.server_wide_modules else [] + if complete: + openerp.modules.module.initialize_sys_path() + openerp.modules.loading.open_openerp_namespace() + # openerp.addons.__path__.extend(openerp.conf.addons_paths) # This + # is not compatible with initialize_sys_path(): import crm and + # import openerp.addons.crm load twice the module. + def _generate_pgpassfile(self): """ Generate the pgpass file with the parameters from the command line (db_host, db_user, diff --git a/openerp/tools/misc.py b/openerp/tools/misc.py index 4aa438e9471..dbccbe5b217 100644 --- a/openerp/tools/misc.py +++ b/openerp/tools/misc.py @@ -984,10 +984,7 @@ def detect_server_timezone(): return 'UTC' def get_server_timezone(): - # timezone detection is safe in multithread, so lazy init is ok here - if (not config['timezone']): - config['timezone'] = detect_server_timezone() - return config['timezone'] + return "UTC" DEFAULT_SERVER_DATE_FORMAT = "%Y-%m-%d" diff --git a/openerp/tools/yaml_import.py b/openerp/tools/yaml_import.py index 00bb79f0499..bb4ce9db87d 100644 --- a/openerp/tools/yaml_import.py +++ b/openerp/tools/yaml_import.py @@ -1,10 +1,12 @@ # -*- encoding: utf-8 -*- +import threading import types import time # used to eval time.strftime expressions from datetime import datetime, timedelta import logging import openerp.pooler as pooler +import openerp.sql_db as sql_db import misc from config import config import yaml_tag @@ -305,7 +307,7 @@ class YamlInterpreter(object): import openerp.osv as osv record, fields = node.items()[0] model = self.get_model(record.model) - if isinstance(model, osv.osv.osv_memory): + if model.is_transient(): record_dict=self.create_osv_memory_record(record, fields) else: self.validate_xml_id(record.id) @@ -331,6 +333,7 @@ class YamlInterpreter(object): def _create_record(self, model, fields): record_dict = {} + fields = fields or {} for field_name, expression in fields.items(): field_value = self._eval_field(model, field_name, expression) record_dict[field_name] = field_value @@ -800,4 +803,19 @@ def yaml_import(cr, module, yamlfile, idref=None, mode='init', noupdate=False): # keeps convention of convert.py convert_yaml_import = yaml_import +def threaded_yaml_import(db_name, module_name, file_name, delay=0): + def f(): + time.sleep(delay) + cr = None + fp = None + try: + cr = sql_db.db_connect(db_name).cursor() + fp = misc.file_open(file_name) + convert_yaml_import(cr, module_name, fp, {}, 'update', True) + finally: + if cr: cr.close() + if fp: fp.close() + threading.Thread(target=f).start() + + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerp/wizard/__init__.py b/openerp/wizard/__init__.py index df0b942d0df..2ed01921afa 100644 --- a/openerp/wizard/__init__.py +++ b/openerp/wizard/__init__.py @@ -44,7 +44,6 @@ class interface(netsvc.Service): def __init__(self, name): assert not self.exists('wizard.'+name), 'The wizard "%s" already exists!' % (name,) super(interface, self).__init__('wizard.'+name) - self.exportMethod(self.execute) self.wiz_name = name def translate_view(self, cr, node, state, lang): @@ -156,7 +155,7 @@ class interface(netsvc.Service): if isinstance(e, except_wizard) \ or isinstance(e, except_osv) \ or isinstance(e, except_orm): - self.abortResponse(2, e.name, 'warning', e.value) + netsvc.abort_response(2, e.name, 'warning', e.value) else: import traceback tb_s = reduce(lambda x, y: x+y, traceback.format_exception( diff --git a/openerp/workflow/wkf_service.py b/openerp/workflow/wkf_service.py index 6f5059e6817..a8d829aa546 100644 --- a/openerp/workflow/wkf_service.py +++ b/openerp/workflow/wkf_service.py @@ -27,27 +27,49 @@ import openerp.netsvc as netsvc import openerp.pooler as pooler class workflow_service(netsvc.Service): - def __init__(self, name='workflow', audience='*'): - netsvc.Service.__init__(self, name, audience) - self.exportMethod(self.trg_write) - self.exportMethod(self.trg_delete) - self.exportMethod(self.trg_create) - self.exportMethod(self.trg_validate) - self.exportMethod(self.trg_redirect) - self.exportMethod(self.trg_trigger) - self.exportMethod(self.clear_cache) + """ + Sometimes you might want to fire a signal or re-evaluate the current state + of a workflow using the service's API. You can access the workflow services + using: + + >>> import netsvc + >>> wf_service = netsvc.LocalService("workflow") + + """ + + def __init__(self, name='workflow'): + netsvc.Service.__init__(self, name) self.wkf_on_create_cache={} def clear_cache(self, cr, uid): self.wkf_on_create_cache[cr.dbname]={} def trg_write(self, uid, res_type, res_id, cr): + """ + Reevaluates the specified workflow instance. Thus if any condition for + a transition have been changed in the backend, then running ``trg_write`` + will move the workflow over that transition. + + :param res_type: the model name + :param res_id: the model instance id the workflow belongs to + :param cr: a database cursor + """ ident = (uid,res_type,res_id) cr.execute('select id from wkf_instance where res_id=%s and res_type=%s and state=%s', (res_id or None,res_type or None, 'active')) for (id,) in cr.fetchall(): instance.update(cr, id, ident) def trg_trigger(self, uid, res_type, res_id, cr): + """ + Activate a trigger. + + If a workflow instance is waiting for a trigger from another model, then this + trigger can be activated if its conditions are met. + + :param res_type: the model name + :param res_id: the model instance id the workflow belongs to + :param cr: a database cursor + """ cr.execute('select instance_id from wkf_triggers where res_id=%s and model=%s', (res_id,res_type)) res = cr.fetchall() for (instance_id,) in res: @@ -56,10 +78,24 @@ class workflow_service(netsvc.Service): instance.update(cr, instance_id, ident) def trg_delete(self, uid, res_type, res_id, cr): + """ + Delete a workflow instance + + :param res_type: the model name + :param res_id: the model instance id the workflow belongs to + :param cr: a database cursor + """ ident = (uid,res_type,res_id) instance.delete(cr, ident) def trg_create(self, uid, res_type, res_id, cr): + """ + Create a new workflow instance + + :param res_type: the model name + :param res_id: the model instance id to own the created worfklow instance + :param cr: a database cursor + """ ident = (uid,res_type,res_id) self.wkf_on_create_cache.setdefault(cr.dbname, {}) if res_type in self.wkf_on_create_cache[cr.dbname]: @@ -72,6 +108,14 @@ class workflow_service(netsvc.Service): instance.create(cr, ident, wkf_id) def trg_validate(self, uid, res_type, res_id, signal, cr): + """ + Fire a signal on a given workflow instance + + :param res_type: the model name + :param res_id: the model instance id the workflow belongs to + :signal: the signal name to be fired + :param cr: a database cursor + """ result = False ident = (uid,res_type,res_id) # ids of all active workflow instances for a corresponding resource (id, model_nam) @@ -81,10 +125,19 @@ class workflow_service(netsvc.Service): result = result or res2 return result - # make all workitems which are waiting for a (subflow) workflow instance - # for the old resource point to the (first active) workflow instance for - # the new resource def trg_redirect(self, uid, res_type, res_id, new_rid, cr): + """ + Re-bind a workflow instance to another instance of the same model. + + Make all workitems which are waiting for a (subflow) workflow instance + for the old resource point to the (first active) workflow instance for + the new resource. + + :param res_type: the model name + :param res_id: the model instance id the workflow belongs to + :param new_rid: the model instance id to own the worfklow instance + :param cr: a database cursor + """ # get ids of wkf instances for the old resource (res_id) #CHECKME: shouldn't we get only active instances? cr.execute('select id, wkf_id from wkf_instance where res_id=%s and res_type=%s', (res_id, res_type)) diff --git a/openerp/wsgi.py b/openerp/wsgi.py new file mode 100644 index 00000000000..e5aa378bf04 --- /dev/null +++ b/openerp/wsgi.py @@ -0,0 +1,411 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2011 OpenERP s.a. (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +""" WSGI stuffs (proof of concept for now) + +This module offers a WSGI interface to OpenERP. + +""" + +import httplib +import urllib +import xmlrpclib +import StringIO + +import logging +import os +import signal +import sys +import threading +import time +import traceback + +import openerp +import openerp.modules +import openerp.tools.config as config +import service.websrv_lib as websrv_lib + +# XML-RPC fault codes. Some care must be taken when changing these: the +# constants are also defined client-side and must remain in sync. +# User code must use the exceptions defined in ``openerp.exceptions`` (not +# create directly ``xmlrpclib.Fault`` objects). +XML_RPC_FAULT_CODE_APPLICATION_ERROR = 1 +XML_RPC_FAULT_CODE_DEFERRED_APPLICATION_ERROR = 2 +XML_RPC_FAULT_CODE_ACCESS_DENIED = 3 +XML_RPC_FAULT_CODE_ACCESS_ERROR = 4 +XML_RPC_FAULT_CODE_WARNING = 5 + +def xmlrpc_return(start_response, service, method, params): + """ + Helper to call a service's method with some params, using a wsgi-supplied + ``start_response`` callback. + + This is the place to look at to see the mapping between core exceptions + and XML-RPC fault codes. + """ + # Map OpenERP core exceptions to XML-RPC fault codes. Specific exceptions + # defined in ``openerp.exceptions`` are mapped to specific fault codes; + # all the other exceptions are mapped to the generic + # XML_RPC_FAULT_CODE_APPLICATION_ERROR value. + # This also mimics SimpleXMLRPCDispatcher._marshaled_dispatch() for + # exception handling. + try: + result = openerp.netsvc.dispatch_rpc(service, method, params) + response = xmlrpclib.dumps((result,), methodresponse=1, allow_none=False, encoding=None) + except openerp.exceptions.Warning, e: + fault = xmlrpclib.Fault(XML_RPC_FAULT_CODE_WARNING, str(e)) + response = xmlrpclib.dumps(fault, allow_none=False, encoding=None) + except openerp.exceptions.AccessError, e: + fault = xmlrpclib.Fault(XML_RPC_FAULT_CODE_ACCESS_ERROR, str(e)) + response = xmlrpclib.dumps(fault, allow_none=False, encoding=None) + except openerp.exceptions.AccessDenied, e: + fault = xmlrpclib.Fault(XML_RPC_FAULT_CODE_ACCESS_DENIED, str(e)) + response = xmlrpclib.dumps(fault, allow_none=False, encoding=None) + except openerp.exceptions.DeferredException, e: + info = e.traceback + # Which one is the best ? + formatted_info = "".join(traceback.format_exception(*info)) + #formatted_info = openerp.tools.exception_to_unicode(e) + '\n' + info + fault = xmlrpclib.Fault(XML_RPC_FAULT_CODE_DEFERRED_APPLICATION_ERROR, formatted_info) + response = xmlrpclib.dumps(fault, allow_none=False, encoding=None) + except Exception, e: + info = sys.exc_info() + # Which one is the best ? + formatted_info = "".join(traceback.format_exception(*info)) + #formatted_info = openerp.tools.exception_to_unicode(e) + '\n' + info + fault = xmlrpclib.Fault(XML_RPC_FAULT_CODE_APPLICATION_ERROR, formatted_info) + response = xmlrpclib.dumps(fault, allow_none=None, encoding=None) + start_response("200 OK", [('Content-Type','text/xml'), ('Content-Length', str(len(response)))]) + return [response] + +def wsgi_xmlrpc(environ, start_response): + """ The main OpenERP WSGI handler.""" + if environ['REQUEST_METHOD'] == 'POST' and environ['PATH_INFO'].startswith('/openerp/6.1/xmlrpc'): + length = int(environ['CONTENT_LENGTH']) + data = environ['wsgi.input'].read(length) + + params, method = xmlrpclib.loads(data) + + path = environ['PATH_INFO'][len('/openerp/6.1/xmlrpc'):] + if path.startswith('/'): path = path[1:] + if path.endswith('/'): p = path[:-1] + path = path.split('/') + + # All routes are hard-coded. + + # No need for a db segment. + if len(path) == 1: + service = path[0] + + if service == 'common': + if method in ('server_version',): + service = 'db' + return xmlrpc_return(start_response, service, method, params) + + # A db segment must be given. + elif len(path) == 2: + service, db_name = path + params = (db_name,) + params + + if service == 'model': + service = 'object' + return xmlrpc_return(start_response, service, method, params) + + # TODO the body has been read, need to raise an exception (not return None). + +def legacy_wsgi_xmlrpc(environ, start_response): + if environ['REQUEST_METHOD'] == 'POST' and environ['PATH_INFO'].startswith('/xmlrpc/'): + length = int(environ['CONTENT_LENGTH']) + data = environ['wsgi.input'].read(length) + path = environ['PATH_INFO'][len('/xmlrpc/'):] # expected to be one of db, object, ... + + params, method = xmlrpclib.loads(data) + return xmlrpc_return(start_response, path, method, params) + +def wsgi_jsonrpc(environ, start_response): + pass + +def wsgi_webdav(environ, start_response): + if environ['REQUEST_METHOD'] == 'OPTIONS' and environ['PATH_INFO'] == '*': + return return_options(environ, start_response) + + http_dir = websrv_lib.find_http_service(environ['PATH_INFO']) + if http_dir: + path = environ['PATH_INFO'][len(http_dir.path):] + if path.startswith('/'): + environ['PATH_INFO'] = path + else: + environ['PATH_INFO'] = '/' + path + return http_to_wsgi(http_dir)(environ, start_response) + +def return_options(environ, start_response): + # Microsoft specific header, see + # http://www.ibm.com/developerworks/rational/library/2089.html + if 'Microsoft' in environ.get('User-Agent', ''): + option = [('MS-Author-Via', 'DAV')] + else: + option = [] + options += [('DAV', '1 2'), ('Allow', 'GET HEAD PROPFIND OPTIONS REPORT')] + start_response("200 OK", [('Content-Length', str(0))] + options) + return [] + +def http_to_wsgi(http_dir): + """ + Turn a BaseHTTPRequestHandler into a WSGI entry point. + + Actually the argument is not a bare BaseHTTPRequestHandler but is wrapped + (as a class, so it needs to be instanciated) in a HTTPDir. + + This code is adapted from wbsrv_lib.MultiHTTPHandler._handle_one_foreign(). + It is a temporary solution: the HTTP sub-handlers (in particular the + document_webdav addon) have to be WSGIfied. + """ + def wsgi_handler(environ, start_response): + + # Extract from the WSGI environment the necessary data. + scheme = environ['wsgi.url_scheme'] + + headers = {} + for key, value in environ.items(): + if key.startswith('HTTP_'): + key = key[5:].replace('_', '-').title() + headers[key] = value + if key == 'CONTENT_LENGTH': + key = key.replace('_', '-').title() + headers[key] = value + if environ.get('Content-Type'): + headers['Content-Type'] = environ['Content-Type'] + + path = urllib.quote(environ.get('PATH_INFO', '')) + if environ.get('QUERY_STRING'): + path += '?' + environ['QUERY_STRING'] + + request_version = 'HTTP/1.1' # TODO + request_line = "%s %s %s\n" % (environ['REQUEST_METHOD'], path, request_version) + + class Dummy(object): + pass + + # Let's pretend we have a server to hand to the handler. + server = Dummy() + server.server_name = environ['SERVER_NAME'] + server.server_port = int(environ['SERVER_PORT']) + + # Initialize the underlying handler and associated auth. provider. + con = openerp.service.websrv_lib.noconnection(environ['wsgi.input']) + handler = http_dir.instanciate_handler(con, environ['REMOTE_ADDR'], server) + + # Populate the handler as if it is called by a regular HTTP server + # and the request is already parsed. + handler.wfile = StringIO.StringIO() + handler.rfile = environ['wsgi.input'] + handler.headers = headers + handler.command = environ['REQUEST_METHOD'] + handler.path = path + handler.request_version = request_version + handler.close_connection = 1 + handler.raw_requestline = request_line + handler.requestline = request_line + + # Handle authentication if there is an auth. provider associated to + # the handler. + if hasattr(handler, 'auth_provider'): + try: + handler.auth_provider.checkRequest(handler, path) + except websrv_lib.AuthRequiredExc, ae: + # Darwin 9.x.x webdav clients will report "HTTP/1.0" to us, while they support (and need) the + # authorisation features of HTTP/1.1 + if request_version != 'HTTP/1.1' and ('Darwin/9.' not in handler.headers.get('User-Agent', '')): + start_response("403 Forbidden", []) + return [] + start_response("401 Authorization required", [ + ('WWW-Authenticate', '%s realm="%s"' % (ae.atype,ae.realm)), + # ('Connection', 'keep-alive'), + ('Content-Type', 'text/html'), + ('Content-Length', 4), # len(self.auth_required_msg) + ]) + return ['Blah'] # self.auth_required_msg + except websrv_lib.AuthRejectedExc,e: + start_response("403 %s" % (e.args[0],), []) + return [] + + method_name = 'do_' + handler.command + + # Support the OPTIONS method even when not provided directly by the + # handler. TODO I would prefer to remove it and fix the handler if + # needed. + if not hasattr(handler, method_name): + if handler.command == 'OPTIONS': + return return_options(environ, start_response) + start_response("501 Unsupported method (%r)" % handler.command, []) + return [] + + # Finally, call the handler's method. + try: + method = getattr(handler, method_name) + method() + # The DAV handler buffers its output and provides a _flush() + # method. + getattr(handler, '_flush', lambda: None)() + response = parse_http_response(handler.wfile.getvalue()) + response_headers = response.getheaders() + body = response.read() + start_response(str(response.status) + ' ' + response.reason, response_headers) + return [body] + except (websrv_lib.AuthRejectedExc, websrv_lib.AuthRequiredExc): + raise + except Exception, e: + start_response("500 Internal error", []) + return [] + + return wsgi_handler + +def parse_http_response(s): + """ Turn a HTTP response string into a httplib.HTTPResponse object.""" + class DummySocket(StringIO.StringIO): + """ + This is used to provide a StringIO to httplib.HTTPResponse + which, instead of taking a file object, expects a socket and + uses its makefile() method. + """ + def makefile(self, *args, **kw): + return self + response = httplib.HTTPResponse(DummySocket(s)) + response.begin() + return response + +# WSGI handlers registered through the register_wsgi_handler() function below. +module_handlers = [] + +def register_wsgi_handler(handler): + """ Register a WSGI handler. + + Handlers are tried in the order they are added. We might provide a way to + register a handler for specific routes later. + """ + module_handlers.append(handler) + +def application(environ, start_response): + """ WSGI entry point.""" + + # Try all handlers until one returns some result (i.e. not None). + wsgi_handlers = [ + wsgi_xmlrpc, + wsgi_jsonrpc, + legacy_wsgi_xmlrpc, + wsgi_webdav + ] + module_handlers + for handler in wsgi_handlers: + result = handler(environ, start_response) + if result is None: + continue + return result + + # We never returned from the loop. + response = 'No handler found.\n' + start_response('404 Not Found', [('Content-Type', 'text/plain'), ('Content-Length', str(len(response)))]) + return [response] + +# The WSGI server, started by start_server(), stopped by stop_server(). +httpd = None + +def serve(): + """ Serve HTTP requests via werkzeug development server. + + If werkzeug can not be imported, we fall back to wsgiref's simple_server. + + Calling this function is blocking, you might want to call it in its own + thread. + """ + + global httpd + + # TODO Change the xmlrpc_* options to http_* + interface = config['xmlrpc_interface'] or '0.0.0.0' + port = config['xmlrpc_port'] + try: + import werkzeug.serving + httpd = werkzeug.serving.make_server(interface, port, application, threaded=True) + logging.getLogger('wsgi').info('HTTP service (werkzeug) running on %s:%s', interface, port) + except ImportError, e: + import wsgiref.simple_server + logging.getLogger('wsgi').warn('Werkzeug module unavailable, falling back to wsgiref.') + httpd = wsgiref.simple_server.make_server(interface, port, application) + logging.getLogger('wsgi').info('HTTP service (wsgiref) running on %s:%s', interface, port) + + httpd.serve_forever() + +def start_server(): + """ Call serve() in its own thread. + + The WSGI server can be shutdown with stop_server() below. + """ + threading.Thread(target=openerp.wsgi.serve).start() + +def stop_server(): + """ Initiate the shutdown of the WSGI server. + + The server is supposed to have been started by start_server() above. + """ + if httpd: + httpd.shutdown() + +# Master process id, can be used for signaling. +arbiter_pid = None + +# Application setup before we can spawn any worker process. +# This is suitable for e.g. gunicorn's on_starting hook. +def on_starting(server): + global arbiter_pid + arbiter_pid = os.getpid() # TODO check if this is true even after replacing the executable + config = openerp.tools.config + #openerp.tools.cache = kill_workers_cache + openerp.netsvc.init_logger() + openerp.osv.osv.start_object_proxy() + openerp.service.web_services.start_web_services() + +# Install our own signal handler on the master process. +def when_ready(server): + # Hijack gunicorn's SIGWINCH handling; we can choose another one. + signal.signal(signal.SIGWINCH, make_winch_handler(server)) + +# Our signal handler will signal a SGIQUIT to all workers. +def make_winch_handler(server): + def handle_winch(sig, fram): + server.kill_workers(signal.SIGQUIT) # This is gunicorn specific. + return handle_winch + +# Kill gracefuly the workers (e.g. because we want to clear their cache). +# This is done by signaling a SIGWINCH to the master process, so it can be +# called by the workers themselves. +def kill_workers(): + try: + os.kill(arbiter_pid, signal.SIGWINCH) + except OSError, e: + if e.errno == errno.ESRCH: # no such pid + return + raise + +class kill_workers_cache(openerp.tools.ormcache): + def clear(self, dbname, *args, **kwargs): + kill_workers() + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/pixmaps/openerp-intro.bmp b/pixmaps/openerp-intro.bmp deleted file mode 100644 index 8d3c9340c9b..00000000000 Binary files a/pixmaps/openerp-intro.bmp and /dev/null differ diff --git a/pixmaps/openerp-slogan.bmp b/pixmaps/openerp-slogan.bmp deleted file mode 100644 index a3cffd104f2..00000000000 Binary files a/pixmaps/openerp-slogan.bmp and /dev/null differ diff --git a/python25-compat/BaseHTTPServer.py b/python25-compat/BaseHTTPServer.py deleted file mode 100644 index 5f2d558b689..00000000000 --- a/python25-compat/BaseHTTPServer.py +++ /dev/null @@ -1,587 +0,0 @@ -"""HTTP server base class. - -Note: the class in this module doesn't implement any HTTP request; see -SimpleHTTPServer for simple implementations of GET, HEAD and POST -(including CGI scripts). It does, however, optionally implement HTTP/1.1 -persistent connections, as of version 0.3. - -Contents: - -- BaseHTTPRequestHandler: HTTP request handler base class -- test: test function - -XXX To do: - -- log requests even later (to capture byte count) -- log user-agent header and other interesting goodies -- send error log to separate file -""" - - -# See also: -# -# HTTP Working Group T. Berners-Lee -# INTERNET-DRAFT R. T. Fielding -# H. Frystyk Nielsen -# Expires September 8, 1995 March 8, 1995 -# -# URL: http://www.ics.uci.edu/pub/ietf/http/draft-ietf-http-v10-spec-00.txt -# -# and -# -# Network Working Group R. Fielding -# Request for Comments: 2616 et al -# Obsoletes: 2068 June 1999 -# Category: Standards Track -# -# URL: http://www.faqs.org/rfcs/rfc2616.html - -# Log files -# --------- -# -# Here's a quote from the NCSA httpd docs about log file format. -# -# | The logfile format is as follows. Each line consists of: -# | -# | host rfc931 authuser [DD/Mon/YYYY:hh:mm:ss] "request" ddd bbbb -# | -# | host: Either the DNS name or the IP number of the remote client -# | rfc931: Any information returned by identd for this person, -# | - otherwise. -# | authuser: If user sent a userid for authentication, the user name, -# | - otherwise. -# | DD: Day -# | Mon: Month (calendar name) -# | YYYY: Year -# | hh: hour (24-hour format, the machine's timezone) -# | mm: minutes -# | ss: seconds -# | request: The first line of the HTTP request as sent by the client. -# | ddd: the status code returned by the server, - if not available. -# | bbbb: the total number of bytes sent, -# | *not including the HTTP/1.0 header*, - if not available -# | -# | You can determine the name of the file accessed through request. -# -# (Actually, the latter is only true if you know the server configuration -# at the time the request was made!) - -__version__ = "0.3" - -__all__ = ["HTTPServer", "BaseHTTPRequestHandler"] - -import sys -import time -import socket # For gethostbyaddr() -import mimetools -import SocketServer - -# Default error message template -DEFAULT_ERROR_MESSAGE = """\ - -Error response - - -

Error response

-

Error code %(code)d. -

Message: %(message)s. -

Error code explanation: %(code)s = %(explain)s. - -""" - -DEFAULT_ERROR_CONTENT_TYPE = "text/html" - -def _quote_html(html): - return html.replace("&", "&").replace("<", "<").replace(">", ">") - -class HTTPServer(SocketServer.TCPServer): - - allow_reuse_address = 1 # Seems to make sense in testing environment - - def server_bind(self): - """Override server_bind to store the server name.""" - SocketServer.TCPServer.server_bind(self) - host, port = self.socket.getsockname()[:2] - self.server_name = socket.getfqdn(host) - self.server_port = port - - -class BaseHTTPRequestHandler(SocketServer.StreamRequestHandler): - - """HTTP request handler base class. - - The following explanation of HTTP serves to guide you through the - code as well as to expose any misunderstandings I may have about - HTTP (so you don't need to read the code to figure out I'm wrong - :-). - - HTTP (HyperText Transfer Protocol) is an extensible protocol on - top of a reliable stream transport (e.g. TCP/IP). The protocol - recognizes three parts to a request: - - 1. One line identifying the request type and path - 2. An optional set of RFC-822-style headers - 3. An optional data part - - The headers and data are separated by a blank line. - - The first line of the request has the form - - - - where is a (case-sensitive) keyword such as GET or POST, - is a string containing path information for the request, - and should be the string "HTTP/1.0" or "HTTP/1.1". - is encoded using the URL encoding scheme (using %xx to signify - the ASCII character with hex code xx). - - The specification specifies that lines are separated by CRLF but - for compatibility with the widest range of clients recommends - servers also handle LF. Similarly, whitespace in the request line - is treated sensibly (allowing multiple spaces between components - and allowing trailing whitespace). - - Similarly, for output, lines ought to be separated by CRLF pairs - but most clients grok LF characters just fine. - - If the first line of the request has the form - - - - (i.e. is left out) then this is assumed to be an HTTP - 0.9 request; this form has no optional headers and data part and - the reply consists of just the data. - - The reply form of the HTTP 1.x protocol again has three parts: - - 1. One line giving the response code - 2. An optional set of RFC-822-style headers - 3. The data - - Again, the headers and data are separated by a blank line. - - The response code line has the form - - - - where is the protocol version ("HTTP/1.0" or "HTTP/1.1"), - is a 3-digit response code indicating success or - failure of the request, and is an optional - human-readable string explaining what the response code means. - - This server parses the request and the headers, and then calls a - function specific to the request type (). Specifically, - a request SPAM will be handled by a method do_SPAM(). If no - such method exists the server sends an error response to the - client. If it exists, it is called with no arguments: - - do_SPAM() - - Note that the request name is case sensitive (i.e. SPAM and spam - are different requests). - - The various request details are stored in instance variables: - - - client_address is the client IP address in the form (host, - port); - - - command, path and version are the broken-down request line; - - - headers is an instance of mimetools.Message (or a derived - class) containing the header information; - - - rfile is a file object open for reading positioned at the - start of the optional input data part; - - - wfile is a file object open for writing. - - IT IS IMPORTANT TO ADHERE TO THE PROTOCOL FOR WRITING! - - The first thing to be written must be the response line. Then - follow 0 or more header lines, then a blank line, and then the - actual data (if any). The meaning of the header lines depends on - the command executed by the server; in most cases, when data is - returned, there should be at least one header line of the form - - Content-type: / - - where and should be registered MIME types, - e.g. "text/html" or "text/plain". - - """ - - # The Python system version, truncated to its first component. - sys_version = "Python/" + sys.version.split()[0] - - # The server software version. You may want to override this. - # The format is multiple whitespace-separated strings, - # where each string is of the form name[/version]. - server_version = "BaseHTTP/" + __version__ - - # The default request version. This only affects responses up until - # the point where the request line is parsed, so it mainly decides what - # the client gets back when sending a malformed request line. - # Most web servers default to HTTP 0.9, i.e. don't send a status line. - default_request_version = "HTTP/0.9" - - def parse_request(self): - """Parse a request (internal). - - The request should be stored in self.raw_requestline; the results - are in self.command, self.path, self.request_version and - self.headers. - - Return True for success, False for failure; on failure, an - error is sent back. - - """ - self.command = None # set in case of error on the first line - self.request_version = version = self.default_request_version - self.close_connection = 1 - requestline = self.raw_requestline - if requestline[-2:] == '\r\n': - requestline = requestline[:-2] - elif requestline[-1:] == '\n': - requestline = requestline[:-1] - self.requestline = requestline - words = requestline.split() - if len(words) == 3: - [command, path, version] = words - if version[:5] != 'HTTP/': - self.send_error(400, "Bad request version (%r)" % version) - return False - try: - base_version_number = version.split('/', 1)[1] - version_number = base_version_number.split(".") - # RFC 2145 section 3.1 says there can be only one "." and - # - major and minor numbers MUST be treated as - # separate integers; - # - HTTP/2.4 is a lower version than HTTP/2.13, which in - # turn is lower than HTTP/12.3; - # - Leading zeros MUST be ignored by recipients. - if len(version_number) != 2: - raise ValueError - version_number = int(version_number[0]), int(version_number[1]) - except (ValueError, IndexError): - self.send_error(400, "Bad request version (%r)" % version) - return False - if version_number >= (1, 1) and self.protocol_version >= "HTTP/1.1": - self.close_connection = 0 - if version_number >= (2, 0): - self.send_error(505, - "Invalid HTTP Version (%s)" % base_version_number) - return False - elif len(words) == 2: - [command, path] = words - self.close_connection = 1 - if command != 'GET': - self.send_error(400, - "Bad HTTP/0.9 request type (%r)" % command) - return False - elif not words: - return False - else: - self.send_error(400, "Bad request syntax (%r)" % requestline) - return False - self.command, self.path, self.request_version = command, path, version - - # Examine the headers and look for a Connection directive - self.headers = self.MessageClass(self.rfile, 0) - - conntype = self.headers.get('Connection', "") - if conntype.lower() == 'close': - self.close_connection = 1 - elif (conntype.lower() == 'keep-alive' and - self.protocol_version >= "HTTP/1.1"): - self.close_connection = 0 - return True - - def handle_one_request(self): - """Handle a single HTTP request. - - You normally don't need to override this method; see the class - __doc__ string for information on how to handle specific HTTP - commands such as GET and POST. - - """ - self.raw_requestline = self.rfile.readline() - if not self.raw_requestline: - self.close_connection = 1 - return - if not self.parse_request(): # An error code has been sent, just exit - return - mname = 'do_' + self.command - if not hasattr(self, mname): - self.send_error(501, "Unsupported method (%r)" % self.command) - return - method = getattr(self, mname) - method() - - def handle(self): - """Handle multiple requests if necessary.""" - self.close_connection = 1 - - self.handle_one_request() - while not self.close_connection: - self.handle_one_request() - - def send_error(self, code, message=None): - """Send and log an error reply. - - Arguments are the error code, and a detailed message. - The detailed message defaults to the short entry matching the - response code. - - This sends an error response (so it must be called before any - output has been generated), logs the error, and finally sends - a piece of HTML explaining the error to the user. - - """ - - try: - short, long = self.responses[code] - except KeyError: - short, long = '???', '???' - if message is None: - message = short - explain = long - self.log_error("code %d, message %s", code, message) - # using _quote_html to prevent Cross Site Scripting attacks (see bug #1100201) - content = (self.error_message_format % - {'code': code, 'message': _quote_html(message), 'explain': explain}) - self.send_response(code, message) - self.send_header("Content-Type", self.error_content_type) - self.send_header('Connection', 'close') - self.end_headers() - if self.command != 'HEAD' and code >= 200 and code not in (204, 304): - self.wfile.write(content) - - error_message_format = DEFAULT_ERROR_MESSAGE - error_content_type = DEFAULT_ERROR_CONTENT_TYPE - - def send_response(self, code, message=None): - """Send the response header and log the response code. - - Also send two standard headers with the server software - version and the current date. - - """ - self.log_request(code) - if message is None: - if code in self.responses: - message = self.responses[code][0] - else: - message = '' - if self.request_version != 'HTTP/0.9': - self.wfile.write("%s %d %s\r\n" % - (self.protocol_version, code, message)) - # print (self.protocol_version, code, message) - self.send_header('Server', self.version_string()) - self.send_header('Date', self.date_time_string()) - - def send_header(self, keyword, value): - """Send a MIME header.""" - if self.request_version != 'HTTP/0.9': - self.wfile.write("%s: %s\r\n" % (keyword, value)) - - if keyword.lower() == 'connection': - if value.lower() == 'close': - self.close_connection = 1 - elif value.lower() == 'keep-alive': - self.close_connection = 0 - - def end_headers(self): - """Send the blank line ending the MIME headers.""" - if self.request_version != 'HTTP/0.9': - self.wfile.write("\r\n") - - def log_request(self, code='-', size='-'): - """Log an accepted request. - - This is called by send_response(). - - """ - - self.log_message('"%s" %s %s', - self.requestline, str(code), str(size)) - - def log_error(self, format, *args): - """Log an error. - - This is called when a request cannot be fulfilled. By - default it passes the message on to log_message(). - - Arguments are the same as for log_message(). - - XXX This should go to the separate error log. - - """ - - self.log_message(format, *args) - - def log_message(self, format, *args): - """Log an arbitrary message. - - This is used by all other logging functions. Override - it if you have specific logging wishes. - - The first argument, FORMAT, is a format string for the - message to be logged. If the format string contains - any % escapes requiring parameters, they should be - specified as subsequent arguments (it's just like - printf!). - - The client host and current date/time are prefixed to - every message. - - """ - - sys.stderr.write("%s - - [%s] %s\n" % - (self.address_string(), - self.log_date_time_string(), - format%args)) - - def version_string(self): - """Return the server software version string.""" - return self.server_version + ' ' + self.sys_version - - def date_time_string(self, timestamp=None): - """Return the current date and time formatted for a message header.""" - if timestamp is None: - timestamp = time.time() - year, month, day, hh, mm, ss, wd, y, z = time.gmtime(timestamp) - s = "%s, %02d %3s %4d %02d:%02d:%02d GMT" % ( - self.weekdayname[wd], - day, self.monthname[month], year, - hh, mm, ss) - return s - - def log_date_time_string(self): - """Return the current time formatted for logging.""" - now = time.time() - year, month, day, hh, mm, ss, x, y, z = time.localtime(now) - s = "%02d/%3s/%04d %02d:%02d:%02d" % ( - day, self.monthname[month], year, hh, mm, ss) - return s - - weekdayname = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] - - monthname = [None, - 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', - 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] - - def address_string(self): - """Return the client address formatted for logging. - - This version looks up the full hostname using gethostbyaddr(), - and tries to find a name that contains at least one dot. - - """ - - host, port = self.client_address[:2] - return socket.getfqdn(host) - - # Essentially static class variables - - # The version of the HTTP protocol we support. - # Set this to HTTP/1.1 to enable automatic keepalive - protocol_version = "HTTP/1.0" - - # The Message-like class used to parse headers - MessageClass = mimetools.Message - - # Table mapping response codes to messages; entries have the - # form {code: (shortmessage, longmessage)}. - # See RFC 2616. - responses = { - 100: ('Continue', 'Request received, please continue'), - 101: ('Switching Protocols', - 'Switching to new protocol; obey Upgrade header'), - - 200: ('OK', 'Request fulfilled, document follows'), - 201: ('Created', 'Document created, URL follows'), - 202: ('Accepted', - 'Request accepted, processing continues off-line'), - 203: ('Non-Authoritative Information', 'Request fulfilled from cache'), - 204: ('No Content', 'Request fulfilled, nothing follows'), - 205: ('Reset Content', 'Clear input form for further input.'), - 206: ('Partial Content', 'Partial content follows.'), - - 300: ('Multiple Choices', - 'Object has several resources -- see URI list'), - 301: ('Moved Permanently', 'Object moved permanently -- see URI list'), - 302: ('Found', 'Object moved temporarily -- see URI list'), - 303: ('See Other', 'Object moved -- see Method and URL list'), - 304: ('Not Modified', - 'Document has not changed since given time'), - 305: ('Use Proxy', - 'You must use proxy specified in Location to access this ' - 'resource.'), - 307: ('Temporary Redirect', - 'Object moved temporarily -- see URI list'), - - 400: ('Bad Request', - 'Bad request syntax or unsupported method'), - 401: ('Unauthorized', - 'No permission -- see authorization schemes'), - 402: ('Payment Required', - 'No payment -- see charging schemes'), - 403: ('Forbidden', - 'Request forbidden -- authorization will not help'), - 404: ('Not Found', 'Nothing matches the given URI'), - 405: ('Method Not Allowed', - 'Specified method is invalid for this server.'), - 406: ('Not Acceptable', 'URI not available in preferred format.'), - 407: ('Proxy Authentication Required', 'You must authenticate with ' - 'this proxy before proceeding.'), - 408: ('Request Timeout', 'Request timed out; try again later.'), - 409: ('Conflict', 'Request conflict.'), - 410: ('Gone', - 'URI no longer exists and has been permanently removed.'), - 411: ('Length Required', 'Client must specify Content-Length.'), - 412: ('Precondition Failed', 'Precondition in headers is false.'), - 413: ('Request Entity Too Large', 'Entity is too large.'), - 414: ('Request-URI Too Long', 'URI is too long.'), - 415: ('Unsupported Media Type', 'Entity body in unsupported format.'), - 416: ('Requested Range Not Satisfiable', - 'Cannot satisfy request range.'), - 417: ('Expectation Failed', - 'Expect condition could not be satisfied.'), - - 500: ('Internal Server Error', 'Server got itself in trouble'), - 501: ('Not Implemented', - 'Server does not support this operation'), - 502: ('Bad Gateway', 'Invalid responses from another server/proxy.'), - 503: ('Service Unavailable', - 'The server cannot process the request due to a high load'), - 504: ('Gateway Timeout', - 'The gateway server did not receive a timely response'), - 505: ('HTTP Version Not Supported', 'Cannot fulfill request.'), - } - - -def test(HandlerClass = BaseHTTPRequestHandler, - ServerClass = HTTPServer, protocol="HTTP/1.0"): - """Test the HTTP request handler class. - - This runs an HTTP server on port 8000 (or the first command line - argument). - - """ - - if sys.argv[1:]: - port = int(sys.argv[1]) - else: - port = 8000 - server_address = ('', port) - - HandlerClass.protocol_version = protocol - httpd = ServerClass(server_address, HandlerClass) - - sa = httpd.socket.getsockname() - print "Serving HTTP on", sa[0], "port", sa[1], "..." - httpd.serve_forever() - - -if __name__ == '__main__': - test() diff --git a/python25-compat/SimpleXMLRPCServer.py b/python25-compat/SimpleXMLRPCServer.py deleted file mode 100644 index 43757a03dda..00000000000 --- a/python25-compat/SimpleXMLRPCServer.py +++ /dev/null @@ -1,611 +0,0 @@ -"""Simple XML-RPC Server. - -This module can be used to create simple XML-RPC servers -by creating a server and either installing functions, a -class instance, or by extending the SimpleXMLRPCServer -class. - -It can also be used to handle XML-RPC requests in a CGI -environment using CGIXMLRPCRequestHandler. - -A list of possible usage patterns follows: - -1. Install functions: - -server = SimpleXMLRPCServer(("localhost", 8000)) -server.register_function(pow) -server.register_function(lambda x,y: x+y, 'add') -server.serve_forever() - -2. Install an instance: - -class MyFuncs: - def __init__(self): - # make all of the string functions available through - # string.func_name - import string - self.string = string - def _listMethods(self): - # implement this method so that system.listMethods - # knows to advertise the strings methods - return list_public_methods(self) + \ - ['string.' + method for method in list_public_methods(self.string)] - def pow(self, x, y): return pow(x, y) - def add(self, x, y) : return x + y - -server = SimpleXMLRPCServer(("localhost", 8000)) -server.register_introspection_functions() -server.register_instance(MyFuncs()) -server.serve_forever() - -3. Install an instance with custom dispatch method: - -class Math: - def _listMethods(self): - # this method must be present for system.listMethods - # to work - return ['add', 'pow'] - def _methodHelp(self, method): - # this method must be present for system.methodHelp - # to work - if method == 'add': - return "add(2,3) => 5" - elif method == 'pow': - return "pow(x, y[, z]) => number" - else: - # By convention, return empty - # string if no help is available - return "" - def _dispatch(self, method, params): - if method == 'pow': - return pow(*params) - elif method == 'add': - return params[0] + params[1] - else: - raise 'bad method' - -server = SimpleXMLRPCServer(("localhost", 8000)) -server.register_introspection_functions() -server.register_instance(Math()) -server.serve_forever() - -4. Subclass SimpleXMLRPCServer: - -class MathServer(SimpleXMLRPCServer): - def _dispatch(self, method, params): - try: - # We are forcing the 'export_' prefix on methods that are - # callable through XML-RPC to prevent potential security - # problems - func = getattr(self, 'export_' + method) - except AttributeError: - raise Exception('method "%s" is not supported' % method) - else: - return func(*params) - - def export_add(self, x, y): - return x + y - -server = MathServer(("localhost", 8000)) -server.serve_forever() - -5. CGI script: - -server = CGIXMLRPCRequestHandler() -server.register_function(pow) -server.handle_request() -""" - -# Written by Brian Quinlan (brian@sweetapp.com). -# Based on code written by Fredrik Lundh. - -import xmlrpclib -from xmlrpclib import Fault -import SocketServer -import BaseHTTPServer -import sys -import os -import traceback -try: - import fcntl -except ImportError: - fcntl = None - -def resolve_dotted_attribute(obj, attr, allow_dotted_names=True): - """resolve_dotted_attribute(a, 'b.c.d') => a.b.c.d - - Resolves a dotted attribute name to an object. Raises - an AttributeError if any attribute in the chain starts with a '_'. - - If the optional allow_dotted_names argument is false, dots are not - supported and this function operates similar to getattr(obj, attr). - """ - - if allow_dotted_names: - attrs = attr.split('.') - else: - attrs = [attr] - - for i in attrs: - if i.startswith('_'): - raise AttributeError( - 'attempt to access private attribute "%s"' % i - ) - else: - obj = getattr(obj,i) - return obj - -def list_public_methods(obj): - """Returns a list of attribute strings, found in the specified - object, which represent callable attributes""" - - return [member for member in dir(obj) - if not member.startswith('_') and - hasattr(getattr(obj, member), '__call__')] - -def remove_duplicates(lst): - """remove_duplicates([2,2,2,1,3,3]) => [3,1,2] - - Returns a copy of a list without duplicates. Every list - item must be hashable and the order of the items in the - resulting list is not defined. - """ - u = {} - for x in lst: - u[x] = 1 - - return u.keys() - -class SimpleXMLRPCDispatcher: - """Mix-in class that dispatches XML-RPC requests. - - This class is used to register XML-RPC method handlers - and then to dispatch them. There should never be any - reason to instantiate this class directly. - """ - - def __init__(self, allow_none, encoding): - self.funcs = {} - self.instance = None - self.allow_none = allow_none - self.encoding = encoding - - def register_instance(self, instance, allow_dotted_names=False): - """Registers an instance to respond to XML-RPC requests. - - Only one instance can be installed at a time. - - If the registered instance has a _dispatch method then that - method will be called with the name of the XML-RPC method and - its parameters as a tuple - e.g. instance._dispatch('add',(2,3)) - - If the registered instance does not have a _dispatch method - then the instance will be searched to find a matching method - and, if found, will be called. Methods beginning with an '_' - are considered private and will not be called by - SimpleXMLRPCServer. - - If a registered function matches a XML-RPC request, then it - will be called instead of the registered instance. - - If the optional allow_dotted_names argument is true and the - instance does not have a _dispatch method, method names - containing dots are supported and resolved, as long as none of - the name segments start with an '_'. - - *** SECURITY WARNING: *** - - Enabling the allow_dotted_names options allows intruders - to access your module's global variables and may allow - intruders to execute arbitrary code on your machine. Only - use this option on a secure, closed network. - - """ - - self.instance = instance - self.allow_dotted_names = allow_dotted_names - - def register_function(self, function, name = None): - """Registers a function to respond to XML-RPC requests. - - The optional name argument can be used to set a Unicode name - for the function. - """ - - if name is None: - name = function.__name__ - self.funcs[name] = function - - def register_introspection_functions(self): - """Registers the XML-RPC introspection methods in the system - namespace. - - see http://xmlrpc.usefulinc.com/doc/reserved.html - """ - - self.funcs.update({'system.listMethods' : self.system_listMethods, - 'system.methodSignature' : self.system_methodSignature, - 'system.methodHelp' : self.system_methodHelp}) - - def register_multicall_functions(self): - """Registers the XML-RPC multicall method in the system - namespace. - - see http://www.xmlrpc.com/discuss/msgReader$1208""" - - self.funcs.update({'system.multicall' : self.system_multicall}) - - def _marshaled_dispatch(self, data, dispatch_method = None): - """Dispatches an XML-RPC method from marshalled (XML) data. - - XML-RPC methods are dispatched from the marshalled (XML) data - using the _dispatch method and the result is returned as - marshalled data. For backwards compatibility, a dispatch - function can be provided as an argument (see comment in - SimpleXMLRPCRequestHandler.do_POST) but overriding the - existing method through subclassing is the prefered means - of changing method dispatch behavior. - """ - - try: - params, method = xmlrpclib.loads(data) - - # generate response - if dispatch_method is not None: - response = dispatch_method(method, params) - else: - response = self._dispatch(method, params) - # wrap response in a singleton tuple - response = (response,) - response = xmlrpclib.dumps(response, methodresponse=1, - allow_none=self.allow_none, encoding=self.encoding) - except Fault, fault: - response = xmlrpclib.dumps(fault, allow_none=self.allow_none, - encoding=self.encoding) - except: - # report exception back to server - exc_type, exc_value, exc_tb = sys.exc_info() - response = xmlrpclib.dumps( - xmlrpclib.Fault(1, "%s:%s" % (exc_type, exc_value)), - encoding=self.encoding, allow_none=self.allow_none, - ) - - return response - - def system_listMethods(self): - """system.listMethods() => ['add', 'subtract', 'multiple'] - - Returns a list of the methods supported by the server.""" - - methods = self.funcs.keys() - if self.instance is not None: - # Instance can implement _listMethod to return a list of - # methods - if hasattr(self.instance, '_listMethods'): - methods = remove_duplicates( - methods + self.instance._listMethods() - ) - # if the instance has a _dispatch method then we - # don't have enough information to provide a list - # of methods - elif not hasattr(self.instance, '_dispatch'): - methods = remove_duplicates( - methods + list_public_methods(self.instance) - ) - methods.sort() - return methods - - def system_methodSignature(self, method_name): - """system.methodSignature('add') => [double, int, int] - - Returns a list describing the signature of the method. In the - above example, the add method takes two integers as arguments - and returns a double result. - - This server does NOT support system.methodSignature.""" - - # See http://xmlrpc.usefulinc.com/doc/sysmethodsig.html - - return 'signatures not supported' - - def system_methodHelp(self, method_name): - """system.methodHelp('add') => "Adds two integers together" - - Returns a string containing documentation for the specified method.""" - - method = None - if method_name in self.funcs: - method = self.funcs[method_name] - elif self.instance is not None: - # Instance can implement _methodHelp to return help for a method - if hasattr(self.instance, '_methodHelp'): - return self.instance._methodHelp(method_name) - # if the instance has a _dispatch method then we - # don't have enough information to provide help - elif not hasattr(self.instance, '_dispatch'): - try: - method = resolve_dotted_attribute( - self.instance, - method_name, - self.allow_dotted_names - ) - except AttributeError: - pass - - # Note that we aren't checking that the method actually - # be a callable object of some kind - if method is None: - return "" - else: - import pydoc - return pydoc.getdoc(method) - - def system_multicall(self, call_list): - """system.multicall([{'methodName': 'add', 'params': [2, 2]}, ...]) => \ -[[4], ...] - - Allows the caller to package multiple XML-RPC calls into a single - request. - - See http://www.xmlrpc.com/discuss/msgReader$1208 - """ - - results = [] - for call in call_list: - method_name = call['methodName'] - params = call['params'] - - try: - # XXX A marshalling error in any response will fail the entire - # multicall. If someone cares they should fix this. - results.append([self._dispatch(method_name, params)]) - except Fault, fault: - results.append( - {'faultCode' : fault.faultCode, - 'faultString' : fault.faultString} - ) - except: - exc_type, exc_value, exc_tb = sys.exc_info() - results.append( - {'faultCode' : 1, - 'faultString' : "%s:%s" % (exc_type, exc_value)} - ) - return results - - def _dispatch(self, method, params): - """Dispatches the XML-RPC method. - - XML-RPC calls are forwarded to a registered function that - matches the called XML-RPC method name. If no such function - exists then the call is forwarded to the registered instance, - if available. - - If the registered instance has a _dispatch method then that - method will be called with the name of the XML-RPC method and - its parameters as a tuple - e.g. instance._dispatch('add',(2,3)) - - If the registered instance does not have a _dispatch method - then the instance will be searched to find a matching method - and, if found, will be called. - - Methods beginning with an '_' are considered private and will - not be called. - """ - - func = None - try: - # check to see if a matching function has been registered - func = self.funcs[method] - except KeyError: - if self.instance is not None: - # check for a _dispatch method - if hasattr(self.instance, '_dispatch'): - return self.instance._dispatch(method, params) - else: - # call instance method directly - try: - func = resolve_dotted_attribute( - self.instance, - method, - self.allow_dotted_names - ) - except AttributeError: - pass - - if func is not None: - return func(*params) - else: - raise Exception('method "%s" is not supported' % method) - -class SimpleXMLRPCRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): - """Simple XML-RPC request handler class. - - Handles all HTTP POST requests and attempts to decode them as - XML-RPC requests. - """ - - # Class attribute listing the accessible path components; - # paths not on this list will result in a 404 error. - rpc_paths = ('/', '/RPC2') - - def is_rpc_path_valid(self): - if self.rpc_paths: - return self.path in self.rpc_paths - else: - # If .rpc_paths is empty, just assume all paths are legal - return True - - def do_POST(self): - """Handles the HTTP POST request. - - Attempts to interpret all HTTP POST requests as XML-RPC calls, - which are forwarded to the server's _dispatch method for handling. - """ - - # Check that the path is legal - if not self.is_rpc_path_valid(): - self.report_404() - return - - try: - # Get arguments by reading body of request. - # We read this in chunks to avoid straining - # socket.read(); around the 10 or 15Mb mark, some platforms - # begin to have problems (bug #792570). - max_chunk_size = 10*1024*1024 - size_remaining = int(self.headers["content-length"]) - L = [] - while size_remaining: - chunk_size = min(size_remaining, max_chunk_size) - L.append(self.rfile.read(chunk_size)) - size_remaining -= len(L[-1]) - data = ''.join(L) - - # In previous versions of SimpleXMLRPCServer, _dispatch - # could be overridden in this class, instead of in - # SimpleXMLRPCDispatcher. To maintain backwards compatibility, - # check to see if a subclass implements _dispatch and dispatch - # using that method if present. - response = self.server._marshaled_dispatch( - data, getattr(self, '_dispatch', None) - ) - except Exception, e: # This should only happen if the module is buggy - # internal error, report as HTTP server error - self.send_response(500) - - # Send information about the exception if requested - if hasattr(self.server, '_send_traceback_header') and \ - self.server._send_traceback_header: - self.send_header("X-exception", str(e)) - self.send_header("X-traceback", traceback.format_exc()) - - self.end_headers() - else: - # got a valid XML RPC response - self.send_response(200) - self.send_header("Content-type", "text/xml") - self.send_header("Content-length", str(len(response))) - self.end_headers() - self.wfile.write(response) - - # shut down the connection - self.wfile.flush() - self.connection.shutdown(1) - - def report_404 (self): - # Report a 404 error - self.send_response(404) - response = 'No such page' - self.send_header("Content-type", "text/plain") - self.send_header("Content-length", str(len(response))) - self.end_headers() - self.wfile.write(response) - # shut down the connection - self.wfile.flush() - self.connection.shutdown(1) - - def log_request(self, code='-', size='-'): - """Selectively log an accepted request.""" - - if self.server.logRequests: - BaseHTTPServer.BaseHTTPRequestHandler.log_request(self, code, size) - -class SimpleXMLRPCServer(SocketServer.TCPServer, - SimpleXMLRPCDispatcher): - """Simple XML-RPC server. - - Simple XML-RPC server that allows functions and a single instance - to be installed to handle requests. The default implementation - attempts to dispatch XML-RPC calls to the functions or instance - installed in the server. Override the _dispatch method inhereted - from SimpleXMLRPCDispatcher to change this behavior. - """ - - allow_reuse_address = True - - # Warning: this is for debugging purposes only! Never set this to True in - # production code, as will be sending out sensitive information (exception - # and stack trace details) when exceptions are raised inside - # SimpleXMLRPCRequestHandler.do_POST - _send_traceback_header = False - - def __init__(self, addr, requestHandler=SimpleXMLRPCRequestHandler, - logRequests=True, allow_none=False, encoding=None, bind_and_activate=True): - self.logRequests = logRequests - - SimpleXMLRPCDispatcher.__init__(self, allow_none, encoding) - SocketServer.TCPServer.__init__(self, addr, requestHandler, bind_and_activate) - - # [Bug #1222790] If possible, set close-on-exec flag; if a - # method spawns a subprocess, the subprocess shouldn't have - # the listening socket open. - if fcntl is not None and hasattr(fcntl, 'FD_CLOEXEC'): - flags = fcntl.fcntl(self.fileno(), fcntl.F_GETFD) - flags |= fcntl.FD_CLOEXEC - fcntl.fcntl(self.fileno(), fcntl.F_SETFD, flags) - -class CGIXMLRPCRequestHandler(SimpleXMLRPCDispatcher): - """Simple handler for XML-RPC data passed through CGI.""" - - def __init__(self, allow_none=False, encoding=None): - SimpleXMLRPCDispatcher.__init__(self, allow_none, encoding) - - def handle_xmlrpc(self, request_text): - """Handle a single XML-RPC request""" - - response = self._marshaled_dispatch(request_text) - - print 'Content-Type: text/xml' - print 'Content-Length: %d' % len(response) - print - sys.stdout.write(response) - - def handle_get(self): - """Handle a single HTTP GET request. - - Default implementation indicates an error because - XML-RPC uses the POST method. - """ - - code = 400 - message, explain = \ - BaseHTTPServer.BaseHTTPRequestHandler.responses[code] - - response = BaseHTTPServer.DEFAULT_ERROR_MESSAGE % \ - { - 'code' : code, - 'message' : message, - 'explain' : explain - } - print 'Status: %d %s' % (code, message) - print 'Content-Type: text/html' - print 'Content-Length: %d' % len(response) - print - sys.stdout.write(response) - - def handle_request(self, request_text = None): - """Handle a single XML-RPC request passed through a CGI post method. - - If no XML data is given then it is read from stdin. The resulting - XML-RPC response is printed to stdout along with the correct HTTP - headers. - """ - - if request_text is None and \ - os.environ.get('REQUEST_METHOD', None) == 'GET': - self.handle_get() - else: - # POST data is normally available through stdin - if request_text is None: - request_text = sys.stdin.read() - - self.handle_xmlrpc(request_text) - -if __name__ == '__main__': - print 'Running XML-RPC server on port 8000' - server = SimpleXMLRPCServer(("localhost", 8000)) - server.register_function(pow) - server.register_function(lambda x,y: x+y, 'add') - server.serve_forever() diff --git a/python25-compat/SocketServer.py b/python25-compat/SocketServer.py deleted file mode 100644 index 2c41fbb6dc0..00000000000 --- a/python25-compat/SocketServer.py +++ /dev/null @@ -1,681 +0,0 @@ -"""Generic socket server classes. - -This module tries to capture the various aspects of defining a server: - -For socket-based servers: - -- address family: - - AF_INET{,6}: IP (Internet Protocol) sockets (default) - - AF_UNIX: Unix domain sockets - - others, e.g. AF_DECNET are conceivable (see -- socket type: - - SOCK_STREAM (reliable stream, e.g. TCP) - - SOCK_DGRAM (datagrams, e.g. UDP) - -For request-based servers (including socket-based): - -- client address verification before further looking at the request - (This is actually a hook for any processing that needs to look - at the request before anything else, e.g. logging) -- how to handle multiple requests: - - synchronous (one request is handled at a time) - - forking (each request is handled by a new process) - - threading (each request is handled by a new thread) - -The classes in this module favor the server type that is simplest to -write: a synchronous TCP/IP server. This is bad class design, but -save some typing. (There's also the issue that a deep class hierarchy -slows down method lookups.) - -There are five classes in an inheritance diagram, four of which represent -synchronous servers of four types: - - +------------+ - | BaseServer | - +------------+ - | - v - +-----------+ +------------------+ - | TCPServer |------->| UnixStreamServer | - +-----------+ +------------------+ - | - v - +-----------+ +--------------------+ - | UDPServer |------->| UnixDatagramServer | - +-----------+ +--------------------+ - -Note that UnixDatagramServer derives from UDPServer, not from -UnixStreamServer -- the only difference between an IP and a Unix -stream server is the address family, which is simply repeated in both -unix server classes. - -Forking and threading versions of each type of server can be created -using the ForkingMixIn and ThreadingMixIn mix-in classes. For -instance, a threading UDP server class is created as follows: - - class ThreadingUDPServer(ThreadingMixIn, UDPServer): pass - -The Mix-in class must come first, since it overrides a method defined -in UDPServer! Setting the various member variables also changes -the behavior of the underlying server mechanism. - -To implement a service, you must derive a class from -BaseRequestHandler and redefine its handle() method. You can then run -various versions of the service by combining one of the server classes -with your request handler class. - -The request handler class must be different for datagram or stream -services. This can be hidden by using the request handler -subclasses StreamRequestHandler or DatagramRequestHandler. - -Of course, you still have to use your head! - -For instance, it makes no sense to use a forking server if the service -contains state in memory that can be modified by requests (since the -modifications in the child process would never reach the initial state -kept in the parent process and passed to each child). In this case, -you can use a threading server, but you will probably have to use -locks to avoid two requests that come in nearly simultaneous to apply -conflicting changes to the server state. - -On the other hand, if you are building e.g. an HTTP server, where all -data is stored externally (e.g. in the file system), a synchronous -class will essentially render the service "deaf" while one request is -being handled -- which may be for a very long time if a client is slow -to reqd all the data it has requested. Here a threading or forking -server is appropriate. - -In some cases, it may be appropriate to process part of a request -synchronously, but to finish processing in a forked child depending on -the request data. This can be implemented by using a synchronous -server and doing an explicit fork in the request handler class -handle() method. - -Another approach to handling multiple simultaneous requests in an -environment that supports neither threads nor fork (or where these are -too expensive or inappropriate for the service) is to maintain an -explicit table of partially finished requests and to use select() to -decide which request to work on next (or whether to handle a new -incoming request). This is particularly important for stream services -where each client can potentially be connected for a long time (if -threads or subprocesses cannot be used). - -Future work: -- Standard classes for Sun RPC (which uses either UDP or TCP) -- Standard mix-in classes to implement various authentication - and encryption schemes -- Standard framework for select-based multiplexing - -XXX Open problems: -- What to do with out-of-band data? - -BaseServer: -- split generic "request" functionality out into BaseServer class. - Copyright (C) 2000 Luke Kenneth Casson Leighton - - example: read entries from a SQL database (requires overriding - get_request() to return a table entry from the database). - entry is processed by a RequestHandlerClass. - -""" - -# Author of the BaseServer patch: Luke Kenneth Casson Leighton - -# XXX Warning! -# There is a test suite for this module, but it cannot be run by the -# standard regression test. -# To run it manually, run Lib/test/test_socketserver.py. - -__version__ = "0.4" - - -import socket -import select -import sys -import os -try: - import threading -except ImportError: - import dummy_threading as threading - -__all__ = ["TCPServer","UDPServer","ForkingUDPServer","ForkingTCPServer", - "ThreadingUDPServer","ThreadingTCPServer","BaseRequestHandler", - "StreamRequestHandler","DatagramRequestHandler", - "ThreadingMixIn", "ForkingMixIn"] -if hasattr(socket, "AF_UNIX"): - __all__.extend(["UnixStreamServer","UnixDatagramServer", - "ThreadingUnixStreamServer", - "ThreadingUnixDatagramServer"]) - -class BaseServer: - - """Base class for server classes. - - Methods for the caller: - - - __init__(server_address, RequestHandlerClass) - - serve_forever(poll_interval=0.5) - - shutdown() - - handle_request() # if you do not use serve_forever() - - fileno() -> int # for select() - - Methods that may be overridden: - - - server_bind() - - server_activate() - - get_request() -> request, client_address - - handle_timeout() - - verify_request(request, client_address) - - server_close() - - process_request(request, client_address) - - close_request(request) - - handle_error() - - Methods for derived classes: - - - finish_request(request, client_address) - - Class variables that may be overridden by derived classes or - instances: - - - timeout - - address_family - - socket_type - - allow_reuse_address - - Instance variables: - - - RequestHandlerClass - - socket - - """ - - timeout = None - - def __init__(self, server_address, RequestHandlerClass): - """Constructor. May be extended, do not override.""" - self.server_address = server_address - self.RequestHandlerClass = RequestHandlerClass - self.__is_shut_down = threading.Event() - self.__serving = False - - def server_activate(self): - """Called by constructor to activate the server. - - May be overridden. - - """ - pass - - def serve_forever(self, poll_interval=0.5): - """Handle one request at a time until shutdown. - - Polls for shutdown every poll_interval seconds. Ignores - self.timeout. If you need to do periodic tasks, do them in - another thread. - """ - self.__serving = True - self.__is_shut_down.clear() - while self.__serving: - # XXX: Consider using another file descriptor or - # connecting to the socket to wake this up instead of - # polling. Polling reduces our responsiveness to a - # shutdown request and wastes cpu at all other times. - r, w, e = select.select([self], [], [], poll_interval) - if r: - self._handle_request_noblock() - self.__is_shut_down.set() - - def shutdown(self): - """Stops the serve_forever loop. - - Blocks until the loop has finished. This must be called while - serve_forever() is running in another thread, or it will - deadlock. - """ - self.__serving = False - self.__is_shut_down.wait() - - # The distinction between handling, getting, processing and - # finishing a request is fairly arbitrary. Remember: - # - # - handle_request() is the top-level call. It calls - # select, get_request(), verify_request() and process_request() - # - get_request() is different for stream or datagram sockets - # - process_request() is the place that may fork a new process - # or create a new thread to finish the request - # - finish_request() instantiates the request handler class; - # this constructor will handle the request all by itself - - def handle_request(self): - """Handle one request, possibly blocking. - - Respects self.timeout. - """ - # Support people who used socket.settimeout() to escape - # handle_request before self.timeout was available. - timeout = self.socket.gettimeout() - if timeout is None: - timeout = self.timeout - elif self.timeout is not None: - timeout = min(timeout, self.timeout) - fd_sets = select.select([self], [], [], timeout) - if not fd_sets[0]: - self.handle_timeout() - return - self._handle_request_noblock() - - def _handle_request_noblock(self): - """Handle one request, without blocking. - - I assume that select.select has returned that the socket is - readable before this function was called, so there should be - no risk of blocking in get_request(). - """ - try: - request, client_address = self.get_request() - except socket.error: - return - if self.verify_request(request, client_address): - try: - self.process_request(request, client_address) - except: - self.handle_error(request, client_address) - self.close_request(request) - - def handle_timeout(self): - """Called if no new request arrives within self.timeout. - - Overridden by ForkingMixIn. - """ - pass - - def verify_request(self, request, client_address): - """Verify the request. May be overridden. - - Return True if we should proceed with this request. - - """ - return True - - def process_request(self, request, client_address): - """Call finish_request. - - Overridden by ForkingMixIn and ThreadingMixIn. - - """ - self.finish_request(request, client_address) - self.close_request(request) - - def server_close(self): - """Called to clean-up the server. - - May be overridden. - - """ - pass - - def finish_request(self, request, client_address): - """Finish one request by instantiating RequestHandlerClass.""" - self.RequestHandlerClass(request, client_address, self) - - def close_request(self, request): - """Called to clean up an individual request.""" - pass - - def handle_error(self, request, client_address): - """Handle an error gracefully. May be overridden. - - The default is to print a traceback and continue. - - """ - print '-'*40 - print 'Exception happened during processing of request from', - print client_address - import traceback - traceback.print_exc() # XXX But this goes to stderr! - print '-'*40 - - -class TCPServer(BaseServer): - - """Base class for various socket-based server classes. - - Defaults to synchronous IP stream (i.e., TCP). - - Methods for the caller: - - - __init__(server_address, RequestHandlerClass, bind_and_activate=True) - - serve_forever(poll_interval=0.5) - - shutdown() - - handle_request() # if you don't use serve_forever() - - fileno() -> int # for select() - - Methods that may be overridden: - - - server_bind() - - server_activate() - - get_request() -> request, client_address - - handle_timeout() - - verify_request(request, client_address) - - process_request(request, client_address) - - close_request(request) - - handle_error() - - Methods for derived classes: - - - finish_request(request, client_address) - - Class variables that may be overridden by derived classes or - instances: - - - timeout - - address_family - - socket_type - - request_queue_size (only for stream sockets) - - allow_reuse_address - - Instance variables: - - - server_address - - RequestHandlerClass - - socket - - """ - - address_family = socket.AF_INET - - socket_type = socket.SOCK_STREAM - - request_queue_size = 5 - - allow_reuse_address = False - - def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True): - """Constructor. May be extended, do not override.""" - BaseServer.__init__(self, server_address, RequestHandlerClass) - self.socket = socket.socket(self.address_family, - self.socket_type) - if bind_and_activate: - self.server_bind() - self.server_activate() - - def server_bind(self): - """Called by constructor to bind the socket. - - May be overridden. - - """ - if self.allow_reuse_address: - self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - self.socket.bind(self.server_address) - self.server_address = self.socket.getsockname() - - def server_activate(self): - """Called by constructor to activate the server. - - May be overridden. - - """ - self.socket.listen(self.request_queue_size) - - def server_close(self): - """Called to clean-up the server. - - May be overridden. - - """ - self.socket.close() - - def fileno(self): - """Return socket file number. - - Interface required by select(). - - """ - return self.socket.fileno() - - def get_request(self): - """Get the request and client address from the socket. - - May be overridden. - - """ - return self.socket.accept() - - def close_request(self, request): - """Called to clean up an individual request.""" - request.close() - - -class UDPServer(TCPServer): - - """UDP server class.""" - - allow_reuse_address = False - - socket_type = socket.SOCK_DGRAM - - max_packet_size = 8192 - - def get_request(self): - data, client_addr = self.socket.recvfrom(self.max_packet_size) - return (data, self.socket), client_addr - - def server_activate(self): - # No need to call listen() for UDP. - pass - - def close_request(self, request): - # No need to close anything. - pass - -class ForkingMixIn: - - """Mix-in class to handle each request in a new process.""" - - timeout = 300 - active_children = None - max_children = 40 - - def collect_children(self): - """Internal routine to wait for children that have exited.""" - if self.active_children is None: return - while len(self.active_children) >= self.max_children: - # XXX: This will wait for any child process, not just ones - # spawned by this library. This could confuse other - # libraries that expect to be able to wait for their own - # children. - try: - pid, status = os.waitpid(0, options=0) - except os.error: - pid = None - if pid not in self.active_children: continue - self.active_children.remove(pid) - - # XXX: This loop runs more system calls than it ought - # to. There should be a way to put the active_children into a - # process group and then use os.waitpid(-pgid) to wait for any - # of that set, but I couldn't find a way to allocate pgids - # that couldn't collide. - for child in self.active_children: - try: - pid, status = os.waitpid(child, os.WNOHANG) - except os.error: - pid = None - if not pid: continue - try: - self.active_children.remove(pid) - except ValueError, e: - raise ValueError('%s. x=%d and list=%r' % (e.message, pid, - self.active_children)) - - def handle_timeout(self): - """Wait for zombies after self.timeout seconds of inactivity. - - May be extended, do not override. - """ - self.collect_children() - - def process_request(self, request, client_address): - """Fork a new subprocess to process the request.""" - self.collect_children() - pid = os.fork() - if pid: - # Parent process - if self.active_children is None: - self.active_children = [] - self.active_children.append(pid) - self.close_request(request) - return - else: - # Child process. - # This must never return, hence os._exit()! - try: - self.finish_request(request, client_address) - os._exit(0) - except: - try: - self.handle_error(request, client_address) - finally: - os._exit(1) - - -class ThreadingMixIn: - """Mix-in class to handle each request in a new thread.""" - - # Decides how threads will act upon termination of the - # main process - daemon_threads = False - - def process_request_thread(self, request, client_address): - """Same as in BaseServer but as a thread. - - In addition, exception handling is done here. - - """ - try: - self.finish_request(request, client_address) - self.close_request(request) - except: - self.handle_error(request, client_address) - self.close_request(request) - - def process_request(self, request, client_address): - """Start a new thread to process the request.""" - t = threading.Thread(target = self.process_request_thread, - args = (request, client_address)) - if self.daemon_threads: - t.setDaemon (1) - t.start() - - -class ForkingUDPServer(ForkingMixIn, UDPServer): pass -class ForkingTCPServer(ForkingMixIn, TCPServer): pass - -class ThreadingUDPServer(ThreadingMixIn, UDPServer): pass -class ThreadingTCPServer(ThreadingMixIn, TCPServer): pass - -if hasattr(socket, 'AF_UNIX'): - - class UnixStreamServer(TCPServer): - address_family = socket.AF_UNIX - - class UnixDatagramServer(UDPServer): - address_family = socket.AF_UNIX - - class ThreadingUnixStreamServer(ThreadingMixIn, UnixStreamServer): pass - - class ThreadingUnixDatagramServer(ThreadingMixIn, UnixDatagramServer): pass - -class BaseRequestHandler: - - """Base class for request handler classes. - - This class is instantiated for each request to be handled. The - constructor sets the instance variables request, client_address - and server, and then calls the handle() method. To implement a - specific service, all you need to do is to derive a class which - defines a handle() method. - - The handle() method can find the request as self.request, the - client address as self.client_address, and the server (in case it - needs access to per-server information) as self.server. Since a - separate instance is created for each request, the handle() method - can define arbitrary other instance variariables. - - """ - - def __init__(self, request, client_address, server): - self.request = request - self.client_address = client_address - self.server = server - try: - self.setup() - self.handle() - self.finish() - finally: - sys.exc_traceback = None # Help garbage collection - - def setup(self): - pass - - def handle(self): - pass - - def finish(self): - pass - - -# The following two classes make it possible to use the same service -# class for stream or datagram servers. -# Each class sets up these instance variables: -# - rfile: a file object from which receives the request is read -# - wfile: a file object to which the reply is written -# When the handle() method returns, wfile is flushed properly - - -class StreamRequestHandler(BaseRequestHandler): - - """Define self.rfile and self.wfile for stream sockets.""" - - # Default buffer sizes for rfile, wfile. - # We default rfile to buffered because otherwise it could be - # really slow for large data (a getc() call per byte); we make - # wfile unbuffered because (a) often after a write() we want to - # read and we need to flush the line; (b) big writes to unbuffered - # files are typically optimized by stdio even when big reads - # aren't. - rbufsize = -1 - wbufsize = 0 - - def setup(self): - self.connection = self.request - self.rfile = self.connection.makefile('rb', self.rbufsize) - self.wfile = self.connection.makefile('wb', self.wbufsize) - - def finish(self): - if not self.wfile.closed: - self.wfile.flush() - self.wfile.close() - self.rfile.close() - - -class DatagramRequestHandler(BaseRequestHandler): - - # XXX Regrettably, I cannot get this working on Linux; - # s.recvfrom() doesn't return a meaningful client address. - - """Define self.rfile and self.wfile for datagram sockets.""" - - def setup(self): - try: - from cStringIO import StringIO - except ImportError: - from StringIO import StringIO - self.packet, self.socket = self.request - self.rfile = StringIO(self.packet) - self.wfile = StringIO() - - def finish(self): - self.socket.sendto(self.wfile.getvalue(), self.client_address) diff --git a/setup.README b/setup.README deleted file mode 100644 index 5ee564ecfb4..00000000000 --- a/setup.README +++ /dev/null @@ -1,27 +0,0 @@ -Some instructions to use setup.py for a user-install. -This file should/will be moved on a proper documentation place later. - -- Possibly clean any left-over of the previous build. - > rm -rf dist openerp_server.egg-info - -- Possibly copy the addons in the server if we want them to be packaged - together: - > rsync -av --delete \ - --exclude .bzr/ \ - --exclude .bzrignore \ - --exclude /__init__.py \ - --exclude /base \ - --exclude /base_quality_interrogation.py \ - openerp/addons - -- Create the user-local directory where we want the package to be installed: - > mkdir -p /home/openerp/openerp-tmp/lib/python2.6/site-packages/ - -- Use --prefix to specify where the package is installed and include that - place in PYTHONPATH: - > PYTHONPATH=/home/openerp/openerp-tmp/lib/python2.6/site-packages/ \ - python setup.py install --prefix=/home/openerp/openerp-tmp - -- Run the main script, again specifying the PYTHONPATH: - > PYTHONPATH=/home/openerp/openerp-tmp/lib/python2.6/site-packages/ \ - /home/openerp/openerp-tmp/bin/openerp-server diff --git a/setup.cfg b/setup.cfg index 483eb2f22e1..2f64223e455 100644 --- a/setup.cfg +++ b/setup.cfg @@ -17,4 +17,4 @@ requires=python >= 2.5 # Need to overwrite the install-part of the RPM to patch # the filenames of the man pages. -install_script=rpminstall_sh.txt +install_script=setup_rpm.sh diff --git a/setup.nsi b/setup.nsi index f9c962ae383..0ea37b0f9e6 100644 --- a/setup.nsi +++ b/setup.nsi @@ -210,6 +210,7 @@ Section OpenERP_Server SectionOpenERP_Server WriteIniStr "$INSTDIR\openerp-server.conf" "options" "db_user" $TextPostgreSQLUsername WriteIniStr "$INSTDIR\openerp-server.conf" "options" "db_password" $TextPostgreSQLPassword WriteIniStr "$INSTDIR\openerp-server.conf" "options" "db_port" $TextPostgreSQLPort + WriteIniStr "$INSTDIR\openerp-server.conf" "options" "pg_path" "$INSTDIR\PostgreSQL\bin" nsExec::Exec '"$INSTDIR\openerp-server.exe" --stop-after-init --logfile "$INSTDIR\openerp-server.log" -s' nsExec::Exec '"$INSTDIR\service\OpenERPServerService.exe" -auto -install' diff --git a/setup.py b/setup.py index e36662b16cc..9595c1a9257 100755 --- a/setup.py +++ b/setup.py @@ -20,57 +20,12 @@ # ############################################################################## -# setup from TinERP -# taken from straw http://www.nongnu.org/straw/index.html -# taken from gnomolicious http://www.nongnu.org/gnomolicious/ -# adapted by Nicolas Évrard -# -# doc/migrate is not included since about 6.1-dev -# doc/tests is not included -# python25-compat/*py should be in the openerp (and imported appropriately) - -import sys -import os +import glob, os, re, setuptools, sys from os.path import join, isfile -import glob -from setuptools import setup, find_packages - -# Backports os.walk with followlinks from python 2.6. -# Needed to add all addons files to data_files for Windows packaging. -def walk_followlinks(top, topdown=True, onerror=None, followlinks=False): - from os.path import join, isdir, islink - from os import listdir, error - - try: - names = listdir(top) - except error, err: - if onerror is not None: - onerror(err) - return - - dirs, nondirs = [], [] - for name in names: - if isdir(join(top, name)): - dirs.append(name) - else: - nondirs.append(name) - - if topdown: - yield top, dirs, nondirs - for name in dirs: - path = join(top, name) - if followlinks or not islink(path): - for x in walk_followlinks(path, topdown, onerror, followlinks): - yield x - if not topdown: - yield top, dirs, nondirs - -if sys.version_info < (2, 6): - os.walk = walk_followlinks +execfile(join('openerp', 'release.py')) py2exe_keywords = {} -py2exe_data_files = [] if os.name == 'nt': import py2exe py2exe_keywords['console'] = [ @@ -89,42 +44,35 @@ if os.name == 'nt': "pydot", "asyncore","asynchat", "reportlab", "vobject", "HTMLParser", "select", "mako", "poplib", "imaplib", "smtplib", "email", "yaml", "DAV", - "uuid", "commands", "openerp", + "uuid", "commands", "openerp", "simplejson", "vatnumber" ], "excludes" : ["Tkconstants","Tkinter","tcl"], } } - # TODO is it still necessary now that we don't use the library.zip file? - def data_files(): - '''For Windows, we consider all the addons as data files. - It seems also that package_data below isn't honored by py2exe.''' - files = [] - os.chdir('openerp') - for (dp, dn, names) in os.walk('addons'): - files.append((join('openerp',dp), map(lambda x: join('openerp', dp, x), names))) - os.chdir('..') - files.append(('openerp', [join('openerp', 'import_xml.rng'),])) - # copy pytz/timzeone - # TODO check if we have to also copy dateutil's timezone data. - import pytz - # Make sure the layout of pytz hasn't changed - assert (pytz.__file__.endswith('__init__.pyc') or - pytz.__file__.endswith('__init__.py')), pytz.__file__ - pytz_dir = os.path.dirname(pytz.__file__) +# List all data files +def data(): + files = [] + for root, dirnames, filenames in os.walk('openerp'): + for filename in filenames: + if not re.match(r'.*(\.pyc|\.pyo|\~)$',filename): + files.append(os.path.join(root, filename)) + d = {} + for v in files: + k=os.path.dirname(v) + if k in d: + d[k].append(v) + else: + d[k]=[v] + r = d.items() + return r - saved_dir = os.getcwd() - os.chdir(pytz_dir) - for dp, dn, names in os.walk('zoneinfo'): - files.append((join('pytz',dp), map(lambda x: join(pytz_dir, dp, x), names))) - os.chdir(saved_dir) +def gen_manifest(): + file_list="\n".join(data()) + open('MANIFEST','w').write(file_list) - return files - py2exe_data_files = data_files() - -execfile(join('openerp', 'release.py')) - -setup(name = name, +setuptools.setup( + name = name, version = version, description = description, long_description = long_desc, @@ -133,18 +81,10 @@ setup(name = name, author_email = author_email, classifiers = filter(None, classifiers.split("\n")), license = license, - data_files = [ - (join('man', 'man1'), ['man/openerp-server.1']), - (join('man', 'man5'), ['man/openerp_serverrc.5']), - ('doc', filter(isfile, glob.glob('doc/*'))), - ] + py2exe_data_files, scripts = ['openerp-server'], - packages = find_packages(), - include_package_data = True, - package_data = { - '': ['*.yml', '*.xml', '*.po', '*.pot', '*.csv'], - }, - dependency_links = ['http://download.gna.org/pychart/'], + data_files = data(), + packages = setuptools.find_packages(), + #include_package_data = True, install_requires = [ # We require the same version as caldav for lxml. 'lxml==2.1.5', @@ -156,6 +96,7 @@ setup(name = name, # It is probably safe to move to PyChart 1.39 (the latest one). # (Let setup.py choose the latest one, and we should check we can remove pychart from # our tree.) + # http://download.gna.org/pychart/ 'pychart', 'pydot', 'pytz', @@ -165,6 +106,7 @@ setup(name = name, 'pywebdav', 'feedparser', 'simplejson >= 2.0', + 'vatnumber', # required by base_vat module ], extras_require = { 'SSL' : ['pyopenssl'], diff --git a/rpminstall_sh.txt b/setup_rpm.sh similarity index 100% rename from rpminstall_sh.txt rename to setup_rpm.sh diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 00000000000..396284efaf7 --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- +import test_xmlrpc diff --git a/tests/test_xmlrpc.py b/tests/test_xmlrpc.py new file mode 100644 index 00000000000..f31efd24803 --- /dev/null +++ b/tests/test_xmlrpc.py @@ -0,0 +1,109 @@ +# -*- coding: utf-8 -*- +# Run with one of these commands: +# > OPENERP_ADDONS_PATH='../../addons/trunk' OPENERP_PORT=8069 \ +# OPENERP_DATABASE=yy PYTHONPATH=. python tests/test_xmlrpc.py +# > OPENERP_ADDONS_PATH='../../addons/trunk' OPENERP_PORT=8069 \ +# OPENERP_DATABASE=yy nosetests tests/test_xmlrpc.py +# > OPENERP_ADDONS_PATH='../../../addons/trunk' OPENERP_PORT=8069 \ +# OPENERP_DATABASE=yy PYTHONPATH=../:. unit2 test_xmlrpc +import os +import time +import unittest2 +import xmlrpclib + +import openerp + +ADDONS_PATH = os.environ['OPENERP_ADDONS_PATH'] +PORT = int(os.environ['OPENERP_PORT']) +DB = os.environ['OPENERP_DATABASE'] + +HOST = '127.0.0.1' + +ADMIN_USER = 'admin' +ADMIN_USER_ID = 1 +ADMIN_PASSWORD = 'admin' + +common_proxy_60 = None +db_proxy_60 = None +object_proxy_60 = None + +common_proxy_61 = None +db_proxy_61 = None +model_proxy_61 = None + +def setUpModule(): + """ + Start the OpenERP server similary to the openerp-server script and + setup some xmlrpclib proxies. + """ + openerp.tools.config['addons_path'] = ADDONS_PATH + openerp.tools.config['xmlrpc_port'] = PORT + openerp.service.start_services() + + global common_proxy_60 + global db_proxy_60 + global object_proxy_60 + + global common_proxy_61 + global db_proxy_61 + global model_proxy_61 + + # Use the old (pre 6.1) API. + url = 'http://%s:%d/xmlrpc/' % (HOST, PORT) + common_proxy_60 = xmlrpclib.ServerProxy(url + 'common') + db_proxy_60 = xmlrpclib.ServerProxy(url + 'db') + object_proxy_60 = xmlrpclib.ServerProxy(url + 'object') + + # Use the new (6.1) API. + url = 'http://%s:%d/openerp/6.1/xmlrpc/' % (HOST, PORT) + common_proxy_61 = xmlrpclib.ServerProxy(url + 'common') + db_proxy_61 = xmlrpclib.ServerProxy(url + 'db') + model_proxy_61 = xmlrpclib.ServerProxy(url + 'model/' + DB) + + # Mmm need to make sure the server is listening for XML-RPC requests. + time.sleep(10) + +def tearDownModule(): + """ Shutdown the OpenERP server similarly to a single ctrl-c. """ + openerp.service.stop_services() + +class test_xmlrpc(unittest2.TestCase): + + def test_00_xmlrpc_create_database_polling(self): + """ + Simulate a OpenERP client requesting the creation of a database and + polling the server until the creation is complete. + """ + progress_id = db_proxy_60.create(ADMIN_PASSWORD, DB, True, False, + ADMIN_PASSWORD) + while True: + time.sleep(1) + progress, users = db_proxy_60.get_progress(ADMIN_PASSWORD, + progress_id) + if progress == 1.0: + break + + def test_xmlrpc_login(self): + """ Try to login on the common service. """ + uid = common_proxy_60.login(DB, ADMIN_USER, ADMIN_PASSWORD) + assert uid == ADMIN_USER_ID + + def test_xmlrpc_ir_model_search(self): + """ Try a search on the object service. """ + ids = object_proxy_60.execute(DB, ADMIN_USER_ID, ADMIN_PASSWORD, + 'ir.model', 'search', []) + assert ids + ids = object_proxy_60.execute(DB, ADMIN_USER_ID, ADMIN_PASSWORD, + 'ir.model', 'search', [], {}) + assert ids + + def test_xmlrpc_61_ir_model_search(self): + """ Try a search on the object service. """ + ids = model_proxy_61.execute(ADMIN_USER_ID, ADMIN_PASSWORD, 'ir.model', 'search', []) + assert ids + ids = model_proxy_61.execute(ADMIN_USER_ID, ADMIN_PASSWORD, 'ir.model', 'search', [], {}) + assert ids + +if __name__ == '__main__': + unittest2.main() +