[MERGE] merge with lp:~openerp-dev/openobject-server/emails-framework
bzr revid: ysa@tinyerp.com-20110215084729-fc7z20hyhiuj1cn2
@@ -1,54 +0,0 @@
|
||||
- |
|
||||
To check that common dangerous operations are not allowed by the safe_eval mechanism, attempt to
|
||||
evaluate unauthorized expressions, and verify that they trigger an error.
|
||||
-
|
||||
1. Try a few common expressions to verify they work with safe_eval
|
||||
-
|
||||
!python {model: ir.model}: |
|
||||
from tools.safe_eval import safe_eval
|
||||
expected = (1, {"a": 9 * 2}, (True, False, None))
|
||||
actual = safe_eval('(1, {"a": 9 * 2}, (True, False, None))')
|
||||
assert actual == expected, "Simple python expressions are not working with safe_eval"
|
||||
-
|
||||
2. Try simple literal definition to verify it works with literal_eval
|
||||
-
|
||||
!python {model: ir.model}: |
|
||||
from tools.safe_eval import literal_eval
|
||||
expected = (1, {"a": 9}, (True, False, None))
|
||||
actual = literal_eval('(1, {"a": 9}, (True, False, None))')
|
||||
assert actual == expected, "Simple python expressions are not working with literal_eval"
|
||||
-
|
||||
3. Try arithmetic expression in literal_eval to verify it does not work
|
||||
-
|
||||
!python {model: ir.model}: |
|
||||
from tools.safe_eval import literal_eval
|
||||
try:
|
||||
literal_eval('(1, {"a": 2*9}, (True, False, None))')
|
||||
assert False, "literal_eval should not accept arithmetic expressions"
|
||||
except ValueError:
|
||||
pass
|
||||
-
|
||||
4. Try forbidden expressions in literal_eval to verify they are not allowed
|
||||
-
|
||||
!python {model: ir.model}: |
|
||||
from tools.safe_eval import literal_eval
|
||||
try:
|
||||
literal_eval('{"a": True.__class__}')
|
||||
assert False, "literal_eval should accept only literals"
|
||||
except ValueError:
|
||||
pass
|
||||
-
|
||||
5. Try forbidden expressions in safe_eval to verify they are not allowed (open)
|
||||
-
|
||||
!python {model: ir.model}: |
|
||||
from tools.safe_eval import safe_eval
|
||||
try:
|
||||
safe_eval('open("/etc/passwd","r")')
|
||||
assert False, "safe_eval should not allow calling open() builtin"
|
||||
except NameError:
|
||||
pass
|
||||
except:
|
||||
# NameError should be raised because open() builtin is not found,
|
||||
# but other exceptions probably indicate that open() was executed!
|
||||
assert False, "safe_eval should not allow calling open() builtin"
|
||||
|
||||
@@ -1,255 +1,19 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
#! /usr/bin/env python
|
||||
# -*- coding: UTF-8 -*-
|
||||
|
||||
"""
|
||||
OpenERP - Server
|
||||
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.
|
||||
"""
|
||||
|
||||
#----------------------------------------------------------
|
||||
# python imports
|
||||
#----------------------------------------------------------
|
||||
import logging
|
||||
import os
|
||||
import signal
|
||||
import sys
|
||||
import threading
|
||||
import traceback
|
||||
|
||||
import release
|
||||
__author__ = release.author
|
||||
__version__ = release.version
|
||||
if __name__ == "__main__":
|
||||
print '-' * 70
|
||||
print "DEPRECATED: you are starting the OpenERP server with its old path,"
|
||||
print "please use the new executable (available in the parent directory)."
|
||||
print '-' * 70
|
||||
|
||||
if os.name == 'posix':
|
||||
import pwd
|
||||
# We DON't log this using the standard logger, because we might mess
|
||||
# with the logfile's permissions. Just do a quick exit here.
|
||||
if pwd.getpwuid(os.getuid())[0] == 'root' :
|
||||
sys.stderr.write("Attempted to run OpenERP server as root. This is not good, aborting.\n")
|
||||
sys.exit(1)
|
||||
|
||||
#----------------------------------------------------------
|
||||
# get logger
|
||||
#----------------------------------------------------------
|
||||
import netsvc
|
||||
logger = logging.getLogger('server')
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# import the tools module so that the commandline parameters are parsed
|
||||
#-----------------------------------------------------------------------
|
||||
import tools
|
||||
logger.info("OpenERP version - %s", release.version)
|
||||
for name, value in [('addons_path', tools.config['addons_path']),
|
||||
('database hostname', tools.config['db_host'] or 'localhost'),
|
||||
('database port', tools.config['db_port'] or '5432'),
|
||||
('database user', tools.config['db_user'])]:
|
||||
logger.info("%s - %s", name, value)
|
||||
|
||||
# Don't allow if the connection to PostgreSQL done by postgres user
|
||||
if tools.config['db_user'] == 'postgres':
|
||||
logger.error("Connecting to the database as 'postgres' user is forbidden, as it present major security issues. Shutting down.")
|
||||
sys.exit(1)
|
||||
|
||||
import time
|
||||
|
||||
#----------------------------------------------------------
|
||||
# init net service
|
||||
#----------------------------------------------------------
|
||||
logger.info('initialising distributed objects services')
|
||||
|
||||
#---------------------------------------------------------------
|
||||
# connect to the database and initialize it with base if needed
|
||||
#---------------------------------------------------------------
|
||||
import pooler
|
||||
|
||||
#----------------------------------------------------------
|
||||
# import basic modules
|
||||
#----------------------------------------------------------
|
||||
import osv
|
||||
import workflow
|
||||
import report
|
||||
import service
|
||||
|
||||
#----------------------------------------------------------
|
||||
# import addons
|
||||
#----------------------------------------------------------
|
||||
|
||||
import addons
|
||||
|
||||
#----------------------------------------------------------
|
||||
# Load and update databases if requested
|
||||
#----------------------------------------------------------
|
||||
|
||||
import service.http_server
|
||||
|
||||
if not ( tools.config["stop_after_init"] or \
|
||||
tools.config["translate_in"] or \
|
||||
tools.config["translate_out"] ):
|
||||
service.http_server.init_servers()
|
||||
service.http_server.init_xmlrpc()
|
||||
service.http_server.init_static_http()
|
||||
|
||||
import service.netrpc_server
|
||||
service.netrpc_server.init_servers()
|
||||
|
||||
if tools.config['db_name']:
|
||||
for dbname in tools.config['db_name'].split(','):
|
||||
db,pool = pooler.get_db_and_pool(dbname, update_module=tools.config['init'] or tools.config['update'], pooljobs=False)
|
||||
cr = db.cursor()
|
||||
|
||||
if tools.config["test_file"]:
|
||||
logger.info('loading test file %s', tools.config["test_file"])
|
||||
tools.convert_yaml_import(cr, 'base', file(tools.config["test_file"]), {}, 'test', True)
|
||||
cr.rollback()
|
||||
|
||||
pool.get('ir.cron')._poolJobs(db.dbname)
|
||||
|
||||
cr.close()
|
||||
|
||||
#----------------------------------------------------------
|
||||
# translation stuff
|
||||
#----------------------------------------------------------
|
||||
if tools.config["translate_out"]:
|
||||
import csv
|
||||
|
||||
if tools.config["language"]:
|
||||
msg = "language %s" % (tools.config["language"],)
|
||||
else:
|
||||
msg = "new language"
|
||||
logger.info('writing translation file for %s to %s', msg, tools.config["translate_out"])
|
||||
|
||||
fileformat = os.path.splitext(tools.config["translate_out"])[-1][1:].lower()
|
||||
buf = file(tools.config["translate_out"], "w")
|
||||
dbname = tools.config['db_name']
|
||||
cr = pooler.get_db(dbname).cursor()
|
||||
tools.trans_export(tools.config["language"], tools.config["translate_modules"] or ["all"], buf, fileformat, cr)
|
||||
cr.close()
|
||||
buf.close()
|
||||
|
||||
logger.info('translation file written successfully')
|
||||
sys.exit(0)
|
||||
|
||||
if tools.config["translate_in"]:
|
||||
context = {'overwrite': tools.config["overwrite_existing_translations"]}
|
||||
dbname = tools.config['db_name']
|
||||
cr = pooler.get_db(dbname).cursor()
|
||||
tools.trans_load(cr,
|
||||
tools.config["translate_in"],
|
||||
tools.config["language"],
|
||||
context=context)
|
||||
tools.trans_update_res_ids(cr)
|
||||
cr.commit()
|
||||
cr.close()
|
||||
sys.exit(0)
|
||||
|
||||
#----------------------------------------------------------------------------------
|
||||
# if we don't want the server to continue to run after initialization, we quit here
|
||||
#----------------------------------------------------------------------------------
|
||||
if tools.config["stop_after_init"]:
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
#----------------------------------------------------------
|
||||
# Launch Servers
|
||||
#----------------------------------------------------------
|
||||
|
||||
LST_SIGNALS = ['SIGINT', 'SIGTERM']
|
||||
|
||||
SIGNALS = dict(
|
||||
[(getattr(signal, sign), sign) for sign in LST_SIGNALS]
|
||||
)
|
||||
|
||||
netsvc.quit_signals_received = 0
|
||||
|
||||
def handler(signum, frame):
|
||||
"""
|
||||
:param signum: the signal number
|
||||
:param frame: the interrupted stack frame or None
|
||||
"""
|
||||
netsvc.quit_signals_received += 1
|
||||
if netsvc.quit_signals_received > 1:
|
||||
sys.stderr.write("Forced shutdown.\n")
|
||||
os._exit(0)
|
||||
|
||||
def dumpstacks(signum, frame):
|
||||
# code from http://stackoverflow.com/questions/132058/getting-stack-trace-from-a-running-python-application#answer-2569696
|
||||
# modified for python 2.5 compatibility
|
||||
thread_map = dict(threading._active, **threading._limbo)
|
||||
id2name = dict([(threadId, thread.getName()) for threadId, thread in thread_map.items()])
|
||||
code = []
|
||||
for threadId, stack in sys._current_frames().items():
|
||||
code.append("\n# Thread: %s(%d)" % (id2name[threadId], threadId))
|
||||
for filename, lineno, name, line in traceback.extract_stack(stack):
|
||||
code.append('File: "%s", line %d, in %s' % (filename, lineno, name))
|
||||
if line:
|
||||
code.append(" %s" % (line.strip()))
|
||||
logging.getLogger('dumpstacks').info("\n".join(code))
|
||||
|
||||
for signum in SIGNALS:
|
||||
signal.signal(signum, handler)
|
||||
|
||||
if os.name == 'posix':
|
||||
signal.signal(signal.SIGQUIT, dumpstacks)
|
||||
|
||||
def quit():
|
||||
netsvc.Agent.quit()
|
||||
netsvc.Server.quitAll()
|
||||
if tools.config['pidfile']:
|
||||
os.unlink(tools.config['pidfile'])
|
||||
logger = logging.getLogger('shutdown')
|
||||
logger.info("Initiating OpenERP Server shutdown")
|
||||
logger.info("Hit CTRL-C again or send a second signal to immediately terminate the server...")
|
||||
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)
|
||||
sys.exit(0)
|
||||
|
||||
if tools.config['pidfile']:
|
||||
fd = open(tools.config['pidfile'], 'w')
|
||||
pidtext = "%d" % (os.getpid())
|
||||
fd.write(pidtext)
|
||||
fd.close()
|
||||
|
||||
netsvc.Server.startAll()
|
||||
|
||||
logger.info('OpenERP server is running, waiting for connections...')
|
||||
|
||||
while netsvc.quit_signals_received == 0:
|
||||
time.sleep(60)
|
||||
|
||||
quit()
|
||||
# Change to the parent directory ...
|
||||
os.chdir(os.path.normpath(os.path.dirname(__file__)))
|
||||
os.chdir('..')
|
||||
# ... and execute the new executable.
|
||||
os.execv('openerp-server.py', sys.argv)
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
@@ -0,0 +1,258 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
"""
|
||||
OpenERP - Server
|
||||
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.
|
||||
"""
|
||||
|
||||
#----------------------------------------------------------
|
||||
# python imports
|
||||
#----------------------------------------------------------
|
||||
import logging
|
||||
import os
|
||||
import signal
|
||||
import sys
|
||||
import threading
|
||||
import traceback
|
||||
|
||||
import openerp.release as release
|
||||
__author__ = release.author
|
||||
__version__ = release.version
|
||||
|
||||
if os.name == 'posix':
|
||||
import pwd
|
||||
# We DON't log this using the standard logger, because we might mess
|
||||
# with the logfile's permissions. Just do a quick exit here.
|
||||
if pwd.getpwuid(os.getuid())[0] == 'root' :
|
||||
sys.stderr.write("Attempted to run OpenERP server as root. This is not good, aborting.\n")
|
||||
sys.exit(1)
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# import the tools module so that the commandline parameters are parsed
|
||||
#-----------------------------------------------------------------------
|
||||
import openerp.tools as tools
|
||||
tools.config.parse_config(sys.argv[1:])
|
||||
|
||||
#----------------------------------------------------------
|
||||
# get logger
|
||||
#----------------------------------------------------------
|
||||
import openerp.netsvc as netsvc
|
||||
netsvc.init_logger()
|
||||
logger = logging.getLogger('server')
|
||||
|
||||
logger.info("OpenERP version - %s", release.version)
|
||||
for name, value in [('addons_path', tools.config['addons_path']),
|
||||
('database hostname', tools.config['db_host'] or 'localhost'),
|
||||
('database port', tools.config['db_port'] or '5432'),
|
||||
('database user', tools.config['db_user'])]:
|
||||
logger.info("%s - %s", name, value)
|
||||
|
||||
# Don't allow if the connection to PostgreSQL done by postgres user
|
||||
if tools.config['db_user'] == 'postgres':
|
||||
logger.error("Connecting to the database as 'postgres' user is forbidden, as it present major security issues. Shutting down.")
|
||||
sys.exit(1)
|
||||
|
||||
import time
|
||||
|
||||
#----------------------------------------------------------
|
||||
# init net service
|
||||
#----------------------------------------------------------
|
||||
logger.info('initialising distributed objects services')
|
||||
|
||||
#---------------------------------------------------------------
|
||||
# connect to the database and initialize it with base if needed
|
||||
#---------------------------------------------------------------
|
||||
import openerp.pooler as pooler
|
||||
|
||||
#----------------------------------------------------------
|
||||
# import basic modules
|
||||
#----------------------------------------------------------
|
||||
import openerp.osv as osv
|
||||
import openerp.workflow as workflow
|
||||
import openerp.report as report
|
||||
import openerp.service as service
|
||||
|
||||
#----------------------------------------------------------
|
||||
# import addons
|
||||
#----------------------------------------------------------
|
||||
|
||||
import openerp.addons as addons
|
||||
|
||||
#----------------------------------------------------------
|
||||
# Load and update databases if requested
|
||||
#----------------------------------------------------------
|
||||
|
||||
import openerp.service.http_server as service_http_server
|
||||
|
||||
if not ( tools.config["stop_after_init"] or \
|
||||
tools.config["translate_in"] or \
|
||||
tools.config["translate_out"] ):
|
||||
service_http_server.init_servers()
|
||||
service_http_server.init_xmlrpc()
|
||||
service_http_server.init_static_http()
|
||||
|
||||
import openerp.service.netrpc_server as service_netrpc_server
|
||||
service_netrpc_server.init_servers()
|
||||
|
||||
if tools.config['db_name']:
|
||||
for dbname in tools.config['db_name'].split(','):
|
||||
db,pool = pooler.get_db_and_pool(dbname, update_module=tools.config['init'] or tools.config['update'], pooljobs=False)
|
||||
cr = db.cursor()
|
||||
|
||||
if tools.config["test_file"]:
|
||||
logger.info('loading test file %s', tools.config["test_file"])
|
||||
tools.convert_yaml_import(cr, 'base', file(tools.config["test_file"]), {}, 'test', True)
|
||||
cr.rollback()
|
||||
|
||||
pool.get('ir.cron')._poolJobs(db.dbname)
|
||||
|
||||
cr.close()
|
||||
|
||||
#----------------------------------------------------------
|
||||
# translation stuff
|
||||
#----------------------------------------------------------
|
||||
if tools.config["translate_out"]:
|
||||
import csv
|
||||
|
||||
if tools.config["language"]:
|
||||
msg = "language %s" % (tools.config["language"],)
|
||||
else:
|
||||
msg = "new language"
|
||||
logger.info('writing translation file for %s to %s', msg, tools.config["translate_out"])
|
||||
|
||||
fileformat = os.path.splitext(tools.config["translate_out"])[-1][1:].lower()
|
||||
buf = file(tools.config["translate_out"], "w")
|
||||
dbname = tools.config['db_name']
|
||||
cr = pooler.get_db(dbname).cursor()
|
||||
tools.trans_export(tools.config["language"], tools.config["translate_modules"] or ["all"], buf, fileformat, cr)
|
||||
cr.close()
|
||||
buf.close()
|
||||
|
||||
logger.info('translation file written successfully')
|
||||
sys.exit(0)
|
||||
|
||||
if tools.config["translate_in"]:
|
||||
context = {'overwrite': tools.config["overwrite_existing_translations"]}
|
||||
dbname = tools.config['db_name']
|
||||
cr = pooler.get_db(dbname).cursor()
|
||||
tools.trans_load(cr,
|
||||
tools.config["translate_in"],
|
||||
tools.config["language"],
|
||||
context=context)
|
||||
tools.trans_update_res_ids(cr)
|
||||
cr.commit()
|
||||
cr.close()
|
||||
sys.exit(0)
|
||||
|
||||
#----------------------------------------------------------------------------------
|
||||
# if we don't want the server to continue to run after initialization, we quit here
|
||||
#----------------------------------------------------------------------------------
|
||||
if tools.config["stop_after_init"]:
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
#----------------------------------------------------------
|
||||
# Launch Servers
|
||||
#----------------------------------------------------------
|
||||
|
||||
LST_SIGNALS = ['SIGINT', 'SIGTERM']
|
||||
|
||||
SIGNALS = dict(
|
||||
[(getattr(signal, sign), sign) for sign in LST_SIGNALS]
|
||||
)
|
||||
|
||||
netsvc.quit_signals_received = 0
|
||||
|
||||
def handler(signum, frame):
|
||||
"""
|
||||
:param signum: the signal number
|
||||
:param frame: the interrupted stack frame or None
|
||||
"""
|
||||
netsvc.quit_signals_received += 1
|
||||
if netsvc.quit_signals_received > 1:
|
||||
sys.stderr.write("Forced shutdown.\n")
|
||||
os._exit(0)
|
||||
|
||||
def dumpstacks(signum, frame):
|
||||
# code from http://stackoverflow.com/questions/132058/getting-stack-trace-from-a-running-python-application#answer-2569696
|
||||
# modified for python 2.5 compatibility
|
||||
thread_map = dict(threading._active, **threading._limbo)
|
||||
id2name = dict([(threadId, thread.getName()) for threadId, thread in thread_map.items()])
|
||||
code = []
|
||||
for threadId, stack in sys._current_frames().items():
|
||||
code.append("\n# Thread: %s(%d)" % (id2name[threadId], threadId))
|
||||
for filename, lineno, name, line in traceback.extract_stack(stack):
|
||||
code.append('File: "%s", line %d, in %s' % (filename, lineno, name))
|
||||
if line:
|
||||
code.append(" %s" % (line.strip()))
|
||||
logging.getLogger('dumpstacks').info("\n".join(code))
|
||||
|
||||
for signum in SIGNALS:
|
||||
signal.signal(signum, handler)
|
||||
|
||||
if os.name == 'posix':
|
||||
signal.signal(signal.SIGQUIT, dumpstacks)
|
||||
|
||||
def quit():
|
||||
netsvc.Agent.quit()
|
||||
netsvc.Server.quitAll()
|
||||
if tools.config['pidfile']:
|
||||
os.unlink(tools.config['pidfile'])
|
||||
logger = logging.getLogger('shutdown')
|
||||
logger.info("Initiating OpenERP Server shutdown")
|
||||
logger.info("Hit CTRL-C again or send a second signal to immediately terminate the server...")
|
||||
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)
|
||||
sys.exit(0)
|
||||
|
||||
if tools.config['pidfile']:
|
||||
fd = open(tools.config['pidfile'], 'w')
|
||||
pidtext = "%d" % (os.getpid())
|
||||
fd.write(pidtext)
|
||||
fd.close()
|
||||
|
||||
netsvc.Server.startAll()
|
||||
|
||||
logger.info('OpenERP server is running, waiting for connections...')
|
||||
|
||||
while netsvc.quit_signals_received == 0:
|
||||
time.sleep(60)
|
||||
|
||||
quit()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
@@ -19,6 +19,23 @@
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import addons
|
||||
import ir
|
||||
import loglevels
|
||||
import netsvc
|
||||
import osv
|
||||
import pooler
|
||||
import pychart
|
||||
import release
|
||||
import report
|
||||
import run_tests
|
||||
import service
|
||||
import sql_db
|
||||
import test
|
||||
import tiny_socket
|
||||
import tools
|
||||
import wizard
|
||||
import workflow
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
@@ -25,17 +25,17 @@ from os.path import join as opj
|
||||
import itertools
|
||||
import zipimport
|
||||
|
||||
import osv
|
||||
import tools
|
||||
import tools.osutil
|
||||
from tools.safe_eval import safe_eval as eval
|
||||
import pooler
|
||||
from tools.translate import _
|
||||
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 netsvc
|
||||
import openerp.netsvc as netsvc
|
||||
|
||||
import zipfile
|
||||
import release
|
||||
import openerp.release as release
|
||||
|
||||
import re
|
||||
import base64
|
||||
@@ -44,25 +44,32 @@ from cStringIO import StringIO
|
||||
|
||||
import logging
|
||||
|
||||
|
||||
logger = netsvc.Logger()
|
||||
|
||||
_ad = os.path.abspath(opj(tools.ustr(tools.config['root_path']), u'addons')) # default addons path (base)
|
||||
ad_paths= map(lambda m: os.path.abspath(tools.ustr(m.strip())), tools.config['addons_path'].split(','))
|
||||
|
||||
sys.path.insert(1, _ad)
|
||||
|
||||
ad_cnt=1
|
||||
for adp in ad_paths:
|
||||
if adp != _ad:
|
||||
sys.path.insert(ad_cnt, adp)
|
||||
ad_cnt+=1
|
||||
|
||||
ad_paths.append(_ad) # for get_module_path
|
||||
_ad = os.path.dirname(__file__) # default addons path (base)
|
||||
ad_paths = []
|
||||
|
||||
# Modules already loaded
|
||||
loaded = []
|
||||
|
||||
def initialize_sys_path():
|
||||
global ad_paths
|
||||
|
||||
if ad_paths:
|
||||
return
|
||||
|
||||
ad_paths = map(lambda m: os.path.abspath(tools.ustr(m.strip())), tools.config['addons_path'].split(','))
|
||||
|
||||
sys.path.insert(1, _ad)
|
||||
|
||||
ad_cnt=1
|
||||
for adp in ad_paths:
|
||||
if adp != _ad:
|
||||
sys.path.insert(ad_cnt, adp)
|
||||
ad_cnt+=1
|
||||
|
||||
ad_paths.append(_ad) # for get_module_path
|
||||
|
||||
class Graph(dict):
|
||||
|
||||
def addNode(self, name, deps):
|
||||
@@ -160,6 +167,7 @@ class Node(Singleton):
|
||||
|
||||
def get_module_path(module, downloaded=False):
|
||||
"""Return the path of the given module."""
|
||||
initialize_sys_path()
|
||||
for adp in ad_paths:
|
||||
if os.path.exists(opj(adp, module)) or os.path.exists(opj(adp, '%s.zip' % module)):
|
||||
return opj(adp, module)
|
||||
@@ -186,7 +194,7 @@ def get_module_filetree(module, dir='.'):
|
||||
zip = zipfile.ZipFile(path + ".zip")
|
||||
files = ['/'.join(f.split('/')[1:]) for f in zip.namelist()]
|
||||
else:
|
||||
files = tools.osutil.listdir(path, True)
|
||||
files = osutil.listdir(path, True)
|
||||
|
||||
tree = {}
|
||||
for f in files:
|
||||
@@ -218,7 +226,7 @@ def zip_directory(directory, b64enc=True, src=True):
|
||||
def _zippy(archive, path, src=True):
|
||||
path = os.path.abspath(path)
|
||||
base = os.path.basename(path)
|
||||
for f in tools.osutil.listdir(path, True):
|
||||
for f in osutil.listdir(path, True):
|
||||
bf = os.path.basename(f)
|
||||
if not RE_exclude.search(bf) and (src or bf in ('__openerp__.py', '__terp__.py') or not bf.endswith('.py')):
|
||||
archive.write(os.path.join(path, f), os.path.join(base, f))
|
||||
@@ -302,6 +310,7 @@ def get_modules():
|
||||
return map(clean, filter(is_really_module, os.listdir(dir)))
|
||||
|
||||
plist = []
|
||||
initialize_sys_path()
|
||||
for ad in ad_paths:
|
||||
plist.extend(listdir(ad))
|
||||
return list(set(plist))
|
||||
@@ -442,6 +451,7 @@ def register_class(m):
|
||||
logger.notifyChannel('init', netsvc.LOG_INFO, 'module %s: registering objects' % m)
|
||||
mod_path = get_module_path(m)
|
||||
|
||||
initialize_sys_path()
|
||||
try:
|
||||
zip_mod_path = mod_path + '.zip'
|
||||
if not os.path.isfile(zip_mod_path):
|
||||
@@ -559,7 +569,7 @@ class MigrationManager(object):
|
||||
a.update(b)
|
||||
return a
|
||||
|
||||
from tools.parse_version import parse_version
|
||||
from openerp.tools.parse_version import parse_version
|
||||
|
||||
parsed_installed_version = parse_version(pkg.installed_version or '')
|
||||
current_version = parse_version(convert_version(pkg.data.get('version', '0')))
|
||||
@@ -798,6 +808,14 @@ def _check_module_names(cr, module_names):
|
||||
logging.getLogger('init').warning('invalid module names, ignored: %s', ", ".join(incorrect_names))
|
||||
|
||||
def load_modules(db, force_demo=False, status=None, update_module=False):
|
||||
|
||||
initialize_sys_path()
|
||||
|
||||
# Backward compatibility: addons don't have to import openerp.xxx, they still can import xxx
|
||||
for k, v in list(sys.modules.items()):
|
||||
if k.startswith('openerp.') and sys.modules.get(k[8:]) is None:
|
||||
sys.modules[k[8:]] = v
|
||||
|
||||
if not status:
|
||||
status = {}
|
||||
cr = db.cursor()
|
||||
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
@@ -7,13 +7,13 @@ msgstr ""
|
||||
"Project-Id-Version: pt_BR\n"
|
||||
"Report-Msgid-Bugs-To: support@openerp.com\n"
|
||||
"POT-Creation-Date: 2011-01-11 11:14+0000\n"
|
||||
"PO-Revision-Date: 2011-01-29 14:51+0000\n"
|
||||
"PO-Revision-Date: 2011-02-02 23:59+0000\n"
|
||||
"Last-Translator: Adriano Prado <adrianojprado@hotmail.com>\n"
|
||||
"Language-Team: <pt@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2011-01-30 04:49+0000\n"
|
||||
"X-Launchpad-Export-Date: 2011-02-05 04:59+0000\n"
|
||||
"X-Generator: Launchpad (build 12177)\n"
|
||||
|
||||
#. module: base
|
||||
@@ -4469,7 +4469,7 @@ msgstr "Empregado"
|
||||
#. module: base
|
||||
#: field:ir.model.access,perm_create:0
|
||||
msgid "Create Access"
|
||||
msgstr "Criar Acesso"
|
||||
msgstr "Acesso Criação"
|
||||
|
||||
#. module: base
|
||||
#: field:res.partner.address,state_id:0
|
||||
@@ -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: 2010-12-16 08:59+0000\n"
|
||||
"Last-Translator: Fabien (Open ERP) <fp@tinyerp.com>\n"
|
||||
"PO-Revision-Date: 2011-02-05 16:25+0000\n"
|
||||
"Last-Translator: Casufi <Unknown>\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-01-12 04:52+0000\n"
|
||||
"X-Generator: Launchpad (build Unknown)\n"
|
||||
"X-Launchpad-Export-Date: 2011-02-06 04:53+0000\n"
|
||||
"X-Generator: Launchpad (build 12177)\n"
|
||||
|
||||
#. module: base
|
||||
#: view:ir.filters:0
|
||||
@@ -23,7 +23,7 @@ msgstr ""
|
||||
#: field:ir.rule,domain_force:0
|
||||
#: field:res.partner.title,domain:0
|
||||
msgid "Domain"
|
||||
msgstr "Категорія"
|
||||
msgstr "Домен"
|
||||
|
||||
#. module: base
|
||||
#: model:res.country,name:base.sh
|
||||
@@ -33,12 +33,12 @@ msgstr "Острів св. Єлени"
|
||||
#. module: base
|
||||
#: view:ir.actions.report.xml:0
|
||||
msgid "Other Configuration"
|
||||
msgstr ""
|
||||
msgstr "Інша конфігурація"
|
||||
|
||||
#. module: base
|
||||
#: selection:ir.property,type:0
|
||||
msgid "DateTime"
|
||||
msgstr ""
|
||||
msgstr "Дата та час"
|
||||
|
||||
#. module: base
|
||||
#: code:addons/fields.py:534
|
||||
@@ -47,6 +47,8 @@ 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 таблиця !Ви "
|
||||
"використовуєте %s, яка не є валідною SQL таблицею."
|
||||
|
||||
#. module: base
|
||||
#: view:ir.values:0
|
||||
@@ -73,7 +75,7 @@ msgstr "Код (напр.:ua__UA)"
|
||||
#: field:workflow.transition,wkf_id:0
|
||||
#: field:workflow.workitem,wkf_id:0
|
||||
msgid "Workflow"
|
||||
msgstr "Процес"
|
||||
msgstr "Робочий процес"
|
||||
|
||||
#. module: base
|
||||
#: view:partner.sms.send:0
|
||||
@@ -93,7 +95,7 @@ msgstr "Пошук неможливий"
|
||||
#. module: base
|
||||
#: selection:base.language.install,lang:0
|
||||
msgid "Spanish (VE) / Español (VE)"
|
||||
msgstr ""
|
||||
msgstr "Іспанська (VE) / Español (VE)"
|
||||
|
||||
#. module: base
|
||||
#: field:ir.actions.server,wkf_model_id:0
|
||||
@@ -103,7 +105,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
|
||||
@@ -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 ""
|
||||
"Ви не можете писати у цьому документі (%s) ! Ви повинні належати до однієї з "
|
||||
"цих груп: %s."
|
||||
|
||||
#. module: base
|
||||
#: help:ir.model.fields,domain:0
|
||||
@@ -129,7 +133,7 @@ msgstr ""
|
||||
#. module: base
|
||||
#: field:res.partner,ref:0
|
||||
msgid "Reference"
|
||||
msgstr ""
|
||||
msgstr "Посилання"
|
||||
|
||||
#. module: base
|
||||
#: field:ir.actions.act_window,target:0
|
||||
@@ -140,7 +144,7 @@ msgstr "Цільове вікно"
|
||||
#: code:addons/base/res/res_user.py:507
|
||||
#, python-format
|
||||
msgid "Warning!"
|
||||
msgstr ""
|
||||
msgstr "Попередження!"
|
||||
|
||||
#. module: base
|
||||
#: code:addons/base/ir/ir_model.py:304
|
||||
@@ -176,7 +180,7 @@ 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
|
||||
@@ -185,6 +189,9 @@ msgid ""
|
||||
"Some installed modules depend on the module you plan to Uninstall :\n"
|
||||
" %s"
|
||||
msgstr ""
|
||||
"Деякі зі встановлених модулів залежать від модуля, який ви плануєте "
|
||||
"вилучити:\n"
|
||||
" %s"
|
||||
|
||||
#. module: base
|
||||
#: field:ir.sequence,number_increment:0
|
||||
@@ -200,7 +207,7 @@ msgstr "Структура компанії"
|
||||
#. module: base
|
||||
#: selection:base.language.install,lang:0
|
||||
msgid "Inuktitut / ᐃᓄᒃᑎᑐᑦ"
|
||||
msgstr ""
|
||||
msgstr "Інуктітут / ᐃᓄᒃᑎᑐᑦ"
|
||||
|
||||
#. module: base
|
||||
#: view:res.partner:0
|
||||
@@ -212,6 +219,8 @@ msgstr "Знайти Партнера"
|
||||
#, python-format
|
||||
msgid "\"smtp_server\" needs to be set to send mails to users"
|
||||
msgstr ""
|
||||
"Для надсилання поштових повідомлень користувачам слід встановити модуль "
|
||||
"\"smtp_server\""
|
||||
|
||||
#. module: base
|
||||
#: code:addons/base/module/wizard/base_export_language.py:60
|
||||
@@ -232,7 +241,7 @@ msgstr "Кількість Модулів"
|
||||
#. module: base
|
||||
#: help:multi_company.default,company_dest_id:0
|
||||
msgid "Company to store the current record"
|
||||
msgstr ""
|
||||
msgstr "Компанія, якої стосується поточний запис"
|
||||
|
||||
#. module: base
|
||||
#: field:res.partner.bank.type.field,size:0
|
||||
@@ -257,7 +266,7 @@ msgstr ""
|
||||
#. 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
|
||||
@@ -288,7 +297,7 @@ msgstr "Дата оновлення"
|
||||
#. module: base
|
||||
#: view:ir.attachment:0
|
||||
msgid "Owner"
|
||||
msgstr ""
|
||||
msgstr "Власник"
|
||||
|
||||
#. module: base
|
||||
#: field:ir.actions.act_window,src_model:0
|
||||
@@ -309,7 +318,7 @@ msgstr "ir.ui.view_sc"
|
||||
#: field:res.widget.user,widget_id:0
|
||||
#: field:res.widget.wizard,widgets_list:0
|
||||
msgid "Widget"
|
||||
msgstr ""
|
||||
msgstr "Віджет"
|
||||
|
||||
#. module: base
|
||||
#: view:ir.model.access:0
|
||||
@@ -389,6 +398,9 @@ 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
|
||||
@@ -405,7 +417,7 @@ msgstr ""
|
||||
#. module: base
|
||||
#: view:base.module.upgrade:0
|
||||
msgid "Your system will be updated."
|
||||
msgstr ""
|
||||
msgstr "Ваша система буде оновлена."
|
||||
|
||||
#. module: base
|
||||
#: field:ir.actions.todo,note:0
|
||||
@@ -432,7 +444,7 @@ msgstr "Запланувати поновлення"
|
||||
#: code:addons/orm.py:838
|
||||
#, python-format
|
||||
msgid "Key/value '%s' not found in selection field '%s'"
|
||||
msgstr ""
|
||||
msgstr "Ключ/значенния '%s' не знайдено у полі відбору '%s'"
|
||||
|
||||
#. module: base
|
||||
#: help:res.country,code:0
|
||||
@@ -456,13 +468,15 @@ msgstr "Збут та постачання"
|
||||
#. module: base
|
||||
#: view:ir.translation:0
|
||||
msgid "Untranslated"
|
||||
msgstr ""
|
||||
msgstr "Не перекладено"
|
||||
|
||||
#. module: base
|
||||
#: help:ir.actions.act_window,context:0
|
||||
msgid ""
|
||||
"Context dictionary as Python expression, empty by default (Default: {})"
|
||||
msgstr ""
|
||||
"Список контекстів у форматі виразу Python, типово порожній (Типове значення: "
|
||||
"{})"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.actions.act_window,name:base.ir_action_wizard
|
||||
@@ -474,7 +488,7 @@ msgstr "Майстри"
|
||||
#. module: base
|
||||
#: model:res.partner.category,name:base.res_partner_category_miscellaneoussuppliers0
|
||||
msgid "Miscellaneous Suppliers"
|
||||
msgstr ""
|
||||
msgstr "Інші постачальники"
|
||||
|
||||
#. module: base
|
||||
#: code:addons/base/ir/ir_model.py:255
|
||||
@@ -490,7 +504,7 @@ msgstr "Виберіть для виконання вікно дії, звіт,
|
||||
#. module: base
|
||||
#: view:res.config.users:0
|
||||
msgid "New User"
|
||||
msgstr ""
|
||||
msgstr "Новий Користувач"
|
||||
|
||||
#. module: base
|
||||
#: view:base.language.export:0
|
||||
@@ -521,7 +535,7 @@ msgstr "Йорданія"
|
||||
#. module: base
|
||||
#: view:ir.module.module:0
|
||||
msgid "Certified"
|
||||
msgstr ""
|
||||
msgstr "Сертифікованою"
|
||||
|
||||
#. module: base
|
||||
#: model:res.country,name:base.er
|
||||
@@ -532,12 +546,12 @@ msgstr "Еритрея"
|
||||
#: view:res.config:0
|
||||
#: view:res.config.installer:0
|
||||
msgid "description"
|
||||
msgstr ""
|
||||
msgstr "опис"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.ui.menu,name:base.menu_base_action_rule
|
||||
msgid "Automated Actions"
|
||||
msgstr ""
|
||||
msgstr "Автоматизовані дії"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.model,name:base.model_ir_actions_actions
|
||||
@@ -547,7 +561,7 @@ msgstr "ir.actions.actions"
|
||||
#. module: base
|
||||
#: view:partner.wizard.ean.check:0
|
||||
msgid "Want to check Ean ? "
|
||||
msgstr ""
|
||||
msgstr "Бажаєте перевірити код EAN ? "
|
||||
|
||||
#. module: base
|
||||
#: field:ir.values,key2:0
|
||||
@@ -561,11 +575,14 @@ msgid ""
|
||||
"Launchpad.net, our open source project management facility. We use their "
|
||||
"online interface to synchronize all translations efforts."
|
||||
msgstr ""
|
||||
"Переклад OpenERP (ядро, модулі, клієнтські програми) керується за допомогую "
|
||||
"Launchpad.net, сервисом призначенним для керування проектами з відкритим "
|
||||
"кодом. Ми використовуємо їх веб-інтерфейс для синхронізації усіх перекладів."
|
||||
|
||||
#. module: base
|
||||
#: field:res.partner,title:0
|
||||
msgid "Partner Form"
|
||||
msgstr ""
|
||||
msgstr "Форма партнера"
|
||||
|
||||
#. module: base
|
||||
#: selection:base.language.install,lang:0
|
||||
@@ -598,27 +615,27 @@ msgstr "Послідовності"
|
||||
#. module: base
|
||||
#: model:ir.model,name:base.model_base_language_import
|
||||
msgid "Language Import"
|
||||
msgstr ""
|
||||
msgstr "Імпорт мови"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.model,name:base.model_res_config_users
|
||||
msgid "res.config.users"
|
||||
msgstr ""
|
||||
msgstr "res.config.users"
|
||||
|
||||
#. module: base
|
||||
#: selection:base.language.install,lang:0
|
||||
msgid "Albanian / Shqip"
|
||||
msgstr ""
|
||||
msgstr "Албанський / Shqip"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.ui.menu,name:base.menu_crm_config_opportunity
|
||||
msgid "Opportunities"
|
||||
msgstr ""
|
||||
msgstr "Можливості"
|
||||
|
||||
#. 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
|
||||
@@ -628,7 +645,7 @@ msgstr "Папуа Нова Гвінея"
|
||||
#. module: base
|
||||
#: help:ir.actions.report.xml,report_type:0
|
||||
msgid "Report Type, e.g. pdf, html, raw, sxw, odt, html2html, mako2html, ..."
|
||||
msgstr ""
|
||||
msgstr "Тип звіту: pdf, html, raw, sxw, odt, html2html, mako2html, ..."
|
||||
|
||||
#. module: base
|
||||
#: model:res.partner.category,name:base.res_partner_category_4
|
||||
@@ -648,7 +665,7 @@ msgstr "Мої Партнери"
|
||||
#. module: base
|
||||
#: view:ir.actions.report.xml:0
|
||||
msgid "XML Report"
|
||||
msgstr ""
|
||||
msgstr "Звіт у XML"
|
||||
|
||||
#. module: base
|
||||
#: model:res.country,name:base.es
|
||||
@@ -664,13 +681,13 @@ msgstr "Імпорт / експорт"
|
||||
#: help:ir.actions.act_window,domain:0
|
||||
msgid ""
|
||||
"Optional domain filtering of the destination data, as a Python expression"
|
||||
msgstr ""
|
||||
msgstr "Опційний фільтр області вихідних даних як 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 "Оновлення Модуля"
|
||||
|
||||
#. module: base
|
||||
#: view:res.config.users:0
|
||||
@@ -678,11 +695,13 @@ 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 ""
|
||||
msgstr "Іспанська (UY) / Español (UY)"
|
||||
|
||||
#. module: base
|
||||
#: field:res.partner,mobile:0
|
||||
@@ -714,7 +733,7 @@ msgstr "Робочі дні"
|
||||
#. module: base
|
||||
#: selection:ir.module.module,license:0
|
||||
msgid "Other OSI Approved Licence"
|
||||
msgstr ""
|
||||
msgstr "Інші ліцензії, рекомендовані OSI"
|
||||
|
||||
#. module: base
|
||||
#: help:res.config.users,context_lang:0
|
||||
@@ -722,7 +741,7 @@ msgstr ""
|
||||
msgid ""
|
||||
"Sets the language for the user's user interface, when UI translations are "
|
||||
"available"
|
||||
msgstr ""
|
||||
msgstr "Встановить мову інтерфейса користувача, якщо переклад в наявності"
|
||||
|
||||
#. module: base
|
||||
#: code:addons/orm.py:1043
|
||||
@@ -745,7 +764,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
|
||||
@@ -766,7 +785,7 @@ msgstr "Дочірні Категорії"
|
||||
#. 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
|
||||
@@ -801,6 +820,8 @@ msgid ""
|
||||
"Language with code \"%s\" is not defined in your system !\n"
|
||||
"Define it through the Administration menu."
|
||||
msgstr ""
|
||||
"Мова з кодом \"%s\" не визначена у системі !\n"
|
||||
"Визначте мову використовуючи Адміністративне меню."
|
||||
|
||||
#. module: base
|
||||
#: model:res.country,name:base.gu
|
||||
@@ -810,7 +831,7 @@ msgstr "Гуам (США)"
|
||||
#. module: base
|
||||
#: model:ir.ui.menu,name:base.menu_hr_project
|
||||
msgid "Human Resources Dashboard"
|
||||
msgstr ""
|
||||
msgstr "Інформаційна панель відділу кадрів"
|
||||
|
||||
#. module: base
|
||||
#: code:addons/base/res/res_user.py:507
|
||||
@@ -2237,7 +2258,7 @@ msgstr "Німецька"
|
||||
#. module: base
|
||||
#: help:ir.actions.server,trigger_name:0
|
||||
msgid "Select the Signal name that is to be used as the trigger."
|
||||
msgstr ""
|
||||
msgstr "Оберіть ім'я сигналу що буде використане як тригер"
|
||||
|
||||
#. module: base
|
||||
#: view:ir.actions.server:0
|
||||
@@ -2279,7 +2300,7 @@ msgstr "Мальта"
|
||||
#. module: base
|
||||
#: field:ir.actions.server,fields_lines:0
|
||||
msgid "Field Mappings."
|
||||
msgstr ""
|
||||
msgstr "Відображення полів"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.model,name:base.model_ir_module_module
|
||||
@@ -2337,7 +2358,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
|
||||
@@ -6587,7 +6608,7 @@ msgstr "Імпорт модуля"
|
||||
#. module: base
|
||||
#: field:ir.actions.server,loop_action:0
|
||||
msgid "Loop Action"
|
||||
msgstr ""
|
||||
msgstr "Дія цикл"
|
||||
|
||||
#. module: base
|
||||
#: help:ir.actions.report.xml,report_file:0
|
||||
@@ -9180,7 +9201,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
|
||||
@@ -9235,7 +9256,7 @@ msgstr "Corp."
|
||||
#. module: base
|
||||
#: model:res.country,name:base.gw
|
||||
msgid "Guinea Bissau"
|
||||
msgstr ""
|
||||
msgstr "Гвінея-Біссау"
|
||||
|
||||
#. module: base
|
||||
#: view:workflow.instance:0
|
||||