diff --git a/chatgpt_bot/__init__.py b/chatgpt_bot/__init__.py
new file mode 100644
index 0000000..19240f4
--- /dev/null
+++ b/chatgpt_bot/__init__.py
@@ -0,0 +1,2 @@
+from . import controllers
+from . import models
\ No newline at end of file
diff --git a/chatgpt_bot/__manifest__.py b/chatgpt_bot/__manifest__.py
new file mode 100644
index 0000000..ebd16d2
--- /dev/null
+++ b/chatgpt_bot/__manifest__.py
@@ -0,0 +1,48 @@
+# -*- coding: utf-8 -*-
+{
+ 'name': "OdooBot ChatGPT AI integration",
+
+ 'summary': """
+ This module integrates the response from ChatGPT into Odoo's built-in chatbot, OdooBot.
+ """,
+
+ 'description': """
+ This module allows users to leverage the advanced natural language processing capabilities
+ of ChatGPT within Odoo's user-friendly interface. By integrating ChatGPT's responses into OdooBot,
+ users can easily access the powerful language model's insights and capabilities without having to
+ navigate away from the Odoo platform. This integration can be used to enhance the functionality of
+ OdooBot, providing more accurate and detailed responses to user queries and improving overall user experience.
+ """,
+
+ 'author': "FL1 sro",
+ 'website': "https://fl1.cz",
+ "images": ["static/description/banner.png", "static/description/gif_chat.gif"],
+ # Categories can be used to filter modules in modules listing
+ # Check https://github.com/odoo/odoo/blob/18.0/odoo/addons/base/data/ir_module_category_data.xml
+ # for the full list
+ 'category': 'Odex25-base',
+ 'version': '18.0.0.1',
+ 'license': 'AGPL-3',
+
+ # any module necessary for this one to work correctly
+ 'depends': ['base', 'mail', 'queue_job'],
+'installable': True,
+ 'application': True, # <-- Important if you want it to appear in "Apps"
+ 'auto_install': False,
+ # always loaded
+ 'data': [
+ # 'security/ir.model.access.csv',
+ 'views/res_config_settings.xml',
+
+ ],
+ # only loaded in demonstration mode
+ 'demo': [
+ 'demo/demo.xml',
+ ],
+ "external_dependencies": {
+ "python": ["openai"]
+ },
+ 'price': 0.00,
+ 'currency': 'EUR',
+
+}
\ No newline at end of file
diff --git a/chatgpt_bot/controllers/__init__.py b/chatgpt_bot/controllers/__init__.py
new file mode 100644
index 0000000..15c7016
--- /dev/null
+++ b/chatgpt_bot/controllers/__init__.py
@@ -0,0 +1,2 @@
+
+from . import controllers
\ No newline at end of file
diff --git a/chatgpt_bot/controllers/controllers.py b/chatgpt_bot/controllers/controllers.py
new file mode 100644
index 0000000..e69de29
diff --git a/chatgpt_bot/demo/demo.xml b/chatgpt_bot/demo/demo.xml
new file mode 100644
index 0000000..17ad66e
--- /dev/null
+++ b/chatgpt_bot/demo/demo.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/chatgpt_bot/images/gif_chat.gif b/chatgpt_bot/images/gif_chat.gif
new file mode 100644
index 0000000..2403faf
Binary files /dev/null and b/chatgpt_bot/images/gif_chat.gif differ
diff --git a/chatgpt_bot/images/image1.png b/chatgpt_bot/images/image1.png
new file mode 100644
index 0000000..da579e6
Binary files /dev/null and b/chatgpt_bot/images/image1.png differ
diff --git a/chatgpt_bot/images/image2.png b/chatgpt_bot/images/image2.png
new file mode 100644
index 0000000..bcca92e
Binary files /dev/null and b/chatgpt_bot/images/image2.png differ
diff --git a/chatgpt_bot/images/image3.png b/chatgpt_bot/images/image3.png
new file mode 100644
index 0000000..953294d
Binary files /dev/null and b/chatgpt_bot/images/image3.png differ
diff --git a/chatgpt_bot/images/image4.png b/chatgpt_bot/images/image4.png
new file mode 100644
index 0000000..7ab9256
Binary files /dev/null and b/chatgpt_bot/images/image4.png differ
diff --git a/chatgpt_bot/models/__init__.py b/chatgpt_bot/models/__init__.py
new file mode 100644
index 0000000..2c78fad
--- /dev/null
+++ b/chatgpt_bot/models/__init__.py
@@ -0,0 +1,5 @@
+# -*- coding: utf-8 -*-
+
+from . import res_config_setting
+from . import mail_bot
+from . import res_users
\ No newline at end of file
diff --git a/chatgpt_bot/models/__pycache__/__init__.cpython-311.pyc b/chatgpt_bot/models/__pycache__/__init__.cpython-311.pyc
new file mode 100644
index 0000000..2a95cc7
Binary files /dev/null and b/chatgpt_bot/models/__pycache__/__init__.cpython-311.pyc differ
diff --git a/chatgpt_bot/models/__pycache__/mail_bot.cpython-311.pyc b/chatgpt_bot/models/__pycache__/mail_bot.cpython-311.pyc
new file mode 100644
index 0000000..b1b84c2
Binary files /dev/null and b/chatgpt_bot/models/__pycache__/mail_bot.cpython-311.pyc differ
diff --git a/chatgpt_bot/models/__pycache__/res_config_setting.cpython-311.pyc b/chatgpt_bot/models/__pycache__/res_config_setting.cpython-311.pyc
new file mode 100644
index 0000000..cc133ca
Binary files /dev/null and b/chatgpt_bot/models/__pycache__/res_config_setting.cpython-311.pyc differ
diff --git a/chatgpt_bot/models/__pycache__/res_users.cpython-311.pyc b/chatgpt_bot/models/__pycache__/res_users.cpython-311.pyc
new file mode 100644
index 0000000..fe1924f
Binary files /dev/null and b/chatgpt_bot/models/__pycache__/res_users.cpython-311.pyc differ
diff --git a/chatgpt_bot/models/mail_bot.py b/chatgpt_bot/models/mail_bot.py
new file mode 100644
index 0000000..7c9279b
--- /dev/null
+++ b/chatgpt_bot/models/mail_bot.py
@@ -0,0 +1,195 @@
+# -*- coding: utf-8 -*-
+from odoo import api, models, _
+from odoo.exceptions import UserError, ValidationError
+from bs4 import BeautifulSoup as BS
+
+# Note: Use the modern OpenAI client
+# pip install openai
+try:
+ from openai import OpenAI
+except Exception: # pragma: no cover
+ OpenAI = None
+
+
+class ChatGptBot(models.AbstractModel):
+ _inherit = 'mail.bot'
+ _description = 'ChatGPT OdooBot'
+
+ #################################################################################################
+ # ORM FUNCTIONS #
+ #################################################################################################
+
+ def create_content(self):
+ """
+ Generates HTML content and SEO JSON via OpenAI and writes back to fields if present.
+ Expected optional fields on the record:
+ - text_chatgpt (input prompt)
+ - content (HTML output)
+ - website_meta_title / website_meta_description / website_meta_keywords (SEO)
+ - is_publish_now / is_published / is_elaborate
+ This method is defensive: if fields do not exist on the record, it skips setting them.
+ """
+ # Ensure running on a single record or abstractly use 'self' as context holder
+ record = self
+
+ # Validate input field existence
+ text = getattr(record, 'text_chatgpt', None)
+ if not text:
+ raise UserError(_("Please provide a prompt (text_chatgpt) before generating content."))
+
+ api_key = self.env['ir.config_parameter'].sudo().get_param('chatgpt_api_key')
+ if not api_key:
+ raise UserError(_("No OpenAI API key configured. Set it in Settings → ChatGPT OdooBot."))
+
+ if OpenAI is None:
+ raise UserError(_("The OpenAI Python package is not installed. Please install 'openai'."))
+
+ # Define an example JSON schema for SEO guidance
+ ex_json = {
+ "title": "Sample Title",
+ "description": "Short description (max 160 characters)",
+ "keywords": "keyword1, keyword2, keyword3"
+ }
+
+ client = OpenAI(api_key=api_key)
+
+ # Prompt instructs the model to output: 1) an HTML
...
, then 2) a pure JSON block
+ system_msg = "You are a helpful assistant that writes clean HTML and valid JSON."
+ user_msg = (
+ f"{text}\n\n"
+ "Output requirements:\n"
+ "1) First, return an HTML block wrapped strictly between and
with headings, paragraphs, and links.\n"
+ "2) Immediately after the closing , return ONLY a valid JSON object (no backticks, no labels)\n"
+ f"matching this schema and rules (description max 160 chars): {ex_json}\n"
+ )
+
+ try:
+ resp = client.chat.completions.create(
+ model="gpt-3.5-turbo",
+ messages=[
+ {"role": "system", "content": system_msg},
+ {"role": "user", "content": user_msg},
+ ],
+ max_tokens=1200,
+ temperature=0.7,
+ )
+ full = resp.choices[0].message.content or ""
+ except Exception as e:
+ raise UserError(_("OpenAI request failed: %s") % str(e))
+
+ # Split HTML and JSON by the first
+ html_part, json_part = "", ""
+ if "" in full:
+ html_part = full.split("", 1)[0] + ""
+ json_part = full.split("", 1)[1].strip()
+
+ # Parse SEO JSON if present
+ title = descr = kw = None
+ if json_part:
+ import json
+ try:
+ seo = json.loads(json_part)
+ title = seo.get("title")
+ descr = seo.get("description")
+ kw = seo.get("keywords")
+ except Exception:
+ # We don't hard-fail if JSON is malformed; raise a friendly error
+ raise ValidationError(_("The SEO JSON response is not valid JSON."))
+
+ # Assign fields defensively if they exist on the record
+ def safe_set(rec, field, value):
+ if hasattr(rec, field):
+ try:
+ setattr(rec, field, value)
+ except Exception:
+ pass
+
+ safe_set(record, 'content', html_part or "")
+ if title:
+ safe_set(record, 'website_meta_title', title)
+ if descr:
+ safe_set(record, 'website_meta_description', descr)
+ if kw:
+ safe_set(record, 'website_meta_keywords', kw)
+
+ # Handle publish flags if the model uses them
+ is_publish_now = getattr(record, 'is_publish_now', False)
+ if is_publish_now and hasattr(record, 'is_published'):
+ safe_set(record, 'is_published', True)
+ elif hasattr(record, 'is_published'):
+ safe_set(record, 'is_published', False)
+
+ safe_set(record, 'is_elaborate', True)
+
+ return True
+
+ #################################################################################################
+ # CUSTOM FUNCTIONS #
+ #################################################################################################
+
+ def _get_answer(self, record, body, values, command=None):
+ """
+ Odoo 18-compatible signature. Adds #enable / #disable and routes to ChatGPT if enabled.
+ """
+ res = super()._get_answer(record, body, values, command=command)
+
+ # Simple toggles
+ if body.strip().lower() == "#enable":
+ self.env.user.odoobot_state = 'chatgpt'
+ return _("ChatGPT enabled")
+ if body.strip().lower() == "#disable":
+ self.env.user.odoobot_state = 'disabled'
+ return _("ChatGPT disabled")
+
+ # Build a short context from last messages (plaintext only)
+ channel = self.env['mail.channel'].browse(record.id)
+ last_ids = channel.message_ids.ids
+ messages = self.env['mail.message'].search([('id', 'in', last_ids)], order='id desc', limit=2).mapped('body')
+ old_conv = ""
+ for msg in messages:
+ if msg:
+ old_conv += BS(msg, 'html.parser').get_text() + "\n"
+
+ # Route to ChatGPT if enabled
+ if self.env.user.odoobot_state == 'chatgpt':
+ return self._chatgpt_reply(record, body, old_conv)
+ return res
+
+ def _chatgpt_reply(self, record, body, context_text=""):
+ api_key = self.env['ir.config_parameter'].sudo().get_param('chatgpt_api_key')
+ if not api_key:
+ raise UserError(_("No OpenAI API key configured. Set it in Settings → ChatGPT OdooBot."))
+
+ if OpenAI is None:
+ raise UserError(_("The OpenAI Python package is not installed. Please install 'openai'."))
+
+ client = OpenAI(api_key=api_key)
+
+ try:
+ messages = []
+ if context_text:
+ messages.append({"role": "system", "content": f"Conversation context:\n{context_text.strip()}"})
+ messages.append({"role": "user", "content": body})
+
+ resp = client.chat.completions.create(
+ model="gpt-3.5-turbo",
+ messages=messages,
+ max_tokens=800,
+ temperature=0.7,
+ )
+ reply = resp.choices[0].message.content or ""
+ except Exception as e:
+ raise UserError(_("OpenAI request failed: %s") % str(e))
+
+ gpt_html = "OpenAI: " + reply
+
+ author_id = self.env.ref("base.partner_root").id
+ subtype_id = self.env.ref("mail.mt_comment").id
+
+ self.env['mail.channel'].browse(record.id).message_post(
+ body=gpt_html,
+ message_type='comment',
+ subtype_id=subtype_id,
+ author_id=author_id,
+ )
+ return gpt_html
diff --git a/chatgpt_bot/models/res_config_setting.py b/chatgpt_bot/models/res_config_setting.py
new file mode 100644
index 0000000..9ec7ac9
--- /dev/null
+++ b/chatgpt_bot/models/res_config_setting.py
@@ -0,0 +1,12 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from odoo import models, fields
+
+class ResConfigSettings(models.TransientModel):
+ _inherit = 'res.config.settings'
+
+ apikey = fields.Char(
+ string="API Key",
+ config_parameter="chatgpt_blog.apikey"
+ )
diff --git a/chatgpt_bot/models/res_users.py b/chatgpt_bot/models/res_users.py
new file mode 100644
index 0000000..739266c
--- /dev/null
+++ b/chatgpt_bot/models/res_users.py
@@ -0,0 +1,10 @@
+from odoo import api, fields, models, _
+
+
+class ResUsers(models.Model):
+ _inherit = 'res.users'
+
+ odoobot_state = fields.Selection(
+ selection_add=[('chatgpt', 'ChatGPT')],
+
+ )
\ No newline at end of file
diff --git a/chatgpt_bot/security/ir.model.access.csv b/chatgpt_bot/security/ir.model.access.csv
new file mode 100644
index 0000000..37ce15d
--- /dev/null
+++ b/chatgpt_bot/security/ir.model.access.csv
@@ -0,0 +1,2 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+access_chatgpt_blog_chatgpt_blog,chatgpt_blog.chatgpt_blog,model_chatgpt_blog_chatgpt_blog,base.group_user,1,1,1,1
\ No newline at end of file
diff --git a/chatgpt_bot/static/description/banner.png b/chatgpt_bot/static/description/banner.png
new file mode 100644
index 0000000..d6ff33f
Binary files /dev/null and b/chatgpt_bot/static/description/banner.png differ
diff --git a/chatgpt_bot/static/description/icon.png b/chatgpt_bot/static/description/icon.png
new file mode 100644
index 0000000..fe52f1f
Binary files /dev/null and b/chatgpt_bot/static/description/icon.png differ
diff --git a/chatgpt_bot/static/description/images/banner.png b/chatgpt_bot/static/description/images/banner.png
new file mode 100644
index 0000000..5799230
Binary files /dev/null and b/chatgpt_bot/static/description/images/banner.png differ
diff --git a/chatgpt_bot/static/description/images/gif_chat.gif b/chatgpt_bot/static/description/images/gif_chat.gif
new file mode 100644
index 0000000..2403faf
Binary files /dev/null and b/chatgpt_bot/static/description/images/gif_chat.gif differ
diff --git a/chatgpt_bot/static/description/images/image1.png b/chatgpt_bot/static/description/images/image1.png
new file mode 100644
index 0000000..da579e6
Binary files /dev/null and b/chatgpt_bot/static/description/images/image1.png differ
diff --git a/chatgpt_bot/static/description/images/image2.png b/chatgpt_bot/static/description/images/image2.png
new file mode 100644
index 0000000..bcca92e
Binary files /dev/null and b/chatgpt_bot/static/description/images/image2.png differ
diff --git a/chatgpt_bot/static/description/images/image3.png b/chatgpt_bot/static/description/images/image3.png
new file mode 100644
index 0000000..953294d
Binary files /dev/null and b/chatgpt_bot/static/description/images/image3.png differ
diff --git a/chatgpt_bot/static/description/images/image4.png b/chatgpt_bot/static/description/images/image4.png
new file mode 100644
index 0000000..7ab9256
Binary files /dev/null and b/chatgpt_bot/static/description/images/image4.png differ
diff --git a/chatgpt_bot/static/description/images/main_screenshot.png b/chatgpt_bot/static/description/images/main_screenshot.png
new file mode 100644
index 0000000..8a5d3f3
Binary files /dev/null and b/chatgpt_bot/static/description/images/main_screenshot.png differ
diff --git a/chatgpt_bot/static/description/index.html b/chatgpt_bot/static/description/index.html
new file mode 100644
index 0000000..7c77196
--- /dev/null
+++ b/chatgpt_bot/static/description/index.html
@@ -0,0 +1,449 @@
+
+
+
+
+
+
+README.rst
+
+
+
+
+
+
+
+
OpenAI ChatGPT Odoo Module
+
+
+This Odoo module allows for seamless integration with the OpenAI ChatGPT API,
+providing advanced natural language processing capabilities within the Odoo platform.
+With this module, users can leverage the power of ChatGPT to generate human-like text,
+perform language translation, and more.
+It utilizes API calls to communicate with the OpenAI service,
+making it easy to set up and use.
+
+
Table of contents
+
+
+
+
Bugfix
+
+fix error when no api key is set
+
+
+
+
Usage
+
To use this module, you need to:
+
+require queque_job from queue_job .
+After the installation to this module, you must change the configuration and add this on the configuration file:
+server_wide_modules = base,web,queue_job add queue_job
+Then restart the server and see a logs file in server console.
+
+
+
This module is required for not blocking the server when the API is called.
+
+
+
Configuration users
+
inside the preferences of the user you can set the chatGPT bot as default bot.
+
+
You can activate or deactivate the chatGPT bot for each user.
+You can activate or deactivate the chatGPT directly in the chat window.
+
You can type: #enable or #disable
+
+
+
+
Example
+
+
+
+
+
Bug Tracker
+
Bugs are tracked on GitHub Issues .
+In case of trouble, please check there if your issue has already been reported.
+If you spotted it first, help us smashing it by providing a detailed and welcomed
+
Do not contact contributors directly about support or help with technical issues.
+
+
+
Credits
+
+
+
+
Maintainers
+
This module is maintained by the FL1.
+
+
+
+
+
+
diff --git a/chatgpt_bot/views/res_config_settings.xml b/chatgpt_bot/views/res_config_settings.xml
new file mode 100644
index 0000000..375cbb6
--- /dev/null
+++ b/chatgpt_bot/views/res_config_settings.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+ res.config.settings.view.form.inherit.chatgpt
+ res.config.settings
+
+
+
+
+
+
+
+
+
+
+
+
+ ChatGPT Settings
+ res.config.settings
+ form
+ current
+ {'module': 'chatgpt_blog'}
+
+
+
+
diff --git a/code_backend_theme/README.rst b/code_backend_theme/README.rst
new file mode 100644
index 0000000..6f5405b
--- /dev/null
+++ b/code_backend_theme/README.rst
@@ -0,0 +1,40 @@
+Code Backend Theme
+==================
+* Code Backend Theme module for Odoo 14 community editions
+
+Installation
+============
+ - www.odoo.com/documentation/14.0/setup/install.html
+ - Install our custom addon
+
+License
+-------
+General Public License, Version 3 (LGPL v3).
+(https://www.odoo.com/documentation/user/14.0/legal/licenses/licenses.html)
+
+Company
+-------
+* 'Cybrosys Techno Solutions '__
+
+Credits
+-------
+* 'Cybrosys Techno Solutions '__
+
+Contacts
+--------
+* Mail Contact : odoo@cybrosys.com
+
+Bug Tracker
+-----------
+Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported.
+
+Maintainer
+==========
+This module is maintained by Cybrosys Technologies.
+
+For support and more information, please visit https://www.cybrosys.com
+
+Further information
+===================
+HTML Description: ``__
+
diff --git a/code_backend_theme/__init__.py b/code_backend_theme/__init__.py
new file mode 100644
index 0000000..eb7442d
--- /dev/null
+++ b/code_backend_theme/__init__.py
@@ -0,0 +1,24 @@
+# -*- coding: utf-8 -*-
+#############################################################################
+#
+# Cybrosys Technologies Pvt. Ltd.
+#
+# Copyright (C) 2021-TODAY Cybrosys Technologies()
+# Author: Cybrosys Techno Solutions()
+#
+# You can modify it under the terms of the GNU LESSER
+# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
+#
+# 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
+#
+# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
+# (LGPL v3) along with this program.
+# If not, see .
+#
+#############################################################################
+from .hooks import post_init_hook
+
+
diff --git a/code_backend_theme/__manifest__.py b/code_backend_theme/__manifest__.py
new file mode 100644
index 0000000..3e29707
--- /dev/null
+++ b/code_backend_theme/__manifest__.py
@@ -0,0 +1,44 @@
+# -*- coding: utf-8 -*-
+{
+ "name": "Code Backend Theme V18",
+ "summary": "Minimalist and elegant backend theme for Odoo 18",
+ "description": """Attractive and modern backend theme for Odoo 18""",
+ "category": "Themes/Backend",
+ "version": "18.0.1.0.0",
+ "author": "Cybrosys Techno Solutions",
+ "company": "Cybrosys Techno Solutions",
+ "maintainer": "Cybrosys Techno Solutions",
+ "website": "https://www.cybrosys.com",
+ "license": "LGPL-3",
+ "depends": ["base", "web", "mail", "account"], # add 'account' if you patch its dashboard
+ "assets": {
+ "web.assets_backend": [
+ # "code_backend_theme/static/src/scss/theme_accent.scss",
+ "code_backend_theme/static/src/scss/navigation_bar.scss",
+ "code_backend_theme/static/src/scss/datetimepicker.scss",
+ "code_backend_theme/static/src/scss/theme.scss",
+ "code_backend_theme/static/src/scss/sidebar.scss",
+ "code_backend_theme/static/src/js/fields/basic_fields.js",
+ "code_backend_theme/static/src/js/fields/graph.js",
+ "code_backend_theme/static/src/js/chrome/sidebar.js",
+ "code_backend_theme/static/src/js/chrome/sidebar_menu.js",
+ ],
+ "web.assets_frontend": [
+ "code_backend_theme/static/src/scss/login.scss",
+ ],
+ "web.qweb": [
+ "code_backend_theme/static/src/xml/sidebar.xml",
+ "code_backend_theme/static/src/xml/styles.xml",
+ "code_backend_theme/static/src/xml/top_bar.xml",
+ ],
+ },
+ "images": [
+ "static/description/banner.png",
+ "static/description/theme_screenshot.png",
+ ],
+
+ "post_init_hook": "post_init_hook",
+ "installable": True,
+ "application": False,
+ "auto_install": False,
+}
diff --git a/code_backend_theme/assets/assets.xml b/code_backend_theme/assets/assets.xml
new file mode 100644
index 0000000..8d5607c
--- /dev/null
+++ b/code_backend_theme/assets/assets.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/code_backend_theme/doc/RELEASE_NOTES.md b/code_backend_theme/doc/RELEASE_NOTES.md
new file mode 100644
index 0000000..f6277ae
--- /dev/null
+++ b/code_backend_theme/doc/RELEASE_NOTES.md
@@ -0,0 +1,21 @@
+## Module
+
+#### 09.06.2021
+#### Version 14.0.1.0.0
+#### ADD
+Initial Commit
+
+#### 18.06.2021
+#### Version 14.0.1.1.0
+#### UPDT
+Made Responsive
+
+#### 27.07.2021
+#### Version 14.0.1.1.1
+#### FIX
+Template not found issue fixed
+
+#### 23.09.2022
+#### Version 14.0.1.1.3
+#### FIX
+List view style issue fixed
\ No newline at end of file
diff --git a/code_backend_theme/hooks.py b/code_backend_theme/hooks.py
new file mode 100644
index 0000000..e4f68b2
--- /dev/null
+++ b/code_backend_theme/hooks.py
@@ -0,0 +1,77 @@
+# -*- coding: utf-8 -*-
+#############################################################################
+#
+# Cybrosys Technologies Pvt. Ltd.
+#
+# Copyright (C) 2021-TODAY Cybrosys Technologies()
+# Author: Cybrosys Techno Solutions()
+#
+# You can modify it under the terms of the GNU LESSER
+# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
+#
+# 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
+#
+# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
+# (LGPL v3) along with this program.
+# If not, see .
+#
+#############################################################################
+import base64
+
+from odoo import api, SUPERUSER_ID
+from odoo.modules import get_module_resource
+
+
+def _set_menu_icons(env):
+ """Helper function to set custom icons for top-level menus."""
+ menu_items = env['ir.ui.menu'].search([('parent_id', '=', False)])
+ icon_map = {
+ 'Contacts': 'Contacts.png',
+ 'Link Tracker': 'Link Tracker.png',
+ 'Dashboards': 'Dashboards.png',
+ 'Sales': 'Sales.png',
+ 'Invoicing': 'Invoicing.png',
+ 'Inventory': 'Inventory.png',
+ 'Purchase': 'Purchase.png',
+ 'Calendar': 'Calendar.png',
+ 'CRM': 'CRM.png',
+ 'Notes': 'Notes.png', # Standardized to 'Notes'
+ 'Website': 'Website.png',
+ 'Point of Sale': 'Point of Sale.png',
+ 'Manufacturing': 'Manufacturing.png',
+ 'Repairs': 'Repairs.png',
+ 'Email Marketing': 'Email Marketing.png',
+ 'SMS Marketing': 'SMS Marketing.png',
+ 'Project': 'Project.png',
+ 'Surveys': 'Surveys.png',
+ 'Employees': 'Employees.png',
+ 'Recruitment': 'Recruitment.png',
+ 'Attendances': 'Attendances.png',
+ 'Time Off': 'Time Off.png',
+ 'Expenses': 'Expenses.png',
+ 'Maintenance': 'Maintenance.png',
+ 'Live Chat': 'Live Chat.png',
+ 'Lunch': 'Lunch.png',
+ 'Fleet': 'Fleet.png',
+ 'Timesheets': 'Timesheets.png',
+ 'Events': 'Events.png',
+ 'eLearning': 'eLearning.png',
+ 'Members': 'Members.png',
+ }
+
+ for menu in menu_items:
+ if menu.name in icon_map:
+ img_path = get_module_resource(
+ 'code_backend_theme', 'static', 'src', 'img', 'icons', icon_map[menu.name]
+ )
+ if img_path:
+ with open(img_path, "rb") as f:
+ menu.write({'web_icon_data': base64.b64encode(f.read())})
+
+
+def post_init_hook(env):
+ """Post-init hook: Set menu icons after module installation."""
+ _set_menu_icons(env)
\ No newline at end of file
diff --git a/code_backend_theme/static/description/assets/all_screens.png b/code_backend_theme/static/description/assets/all_screens.png
new file mode 100644
index 0000000..1844463
Binary files /dev/null and b/code_backend_theme/static/description/assets/all_screens.png differ
diff --git a/code_backend_theme/static/description/assets/hero.png b/code_backend_theme/static/description/assets/hero.png
new file mode 100644
index 0000000..48572a3
Binary files /dev/null and b/code_backend_theme/static/description/assets/hero.png differ
diff --git a/code_backend_theme/static/description/assets/icons/._.DS_Store b/code_backend_theme/static/description/assets/icons/._.DS_Store
new file mode 100644
index 0000000..9ad849c
Binary files /dev/null and b/code_backend_theme/static/description/assets/icons/._.DS_Store differ
diff --git a/code_backend_theme/static/description/assets/icons/._cogs.png b/code_backend_theme/static/description/assets/icons/._cogs.png
new file mode 100644
index 0000000..f7148d4
Binary files /dev/null and b/code_backend_theme/static/description/assets/icons/._cogs.png differ
diff --git a/code_backend_theme/static/description/assets/icons/._consultation.png b/code_backend_theme/static/description/assets/icons/._consultation.png
new file mode 100644
index 0000000..aa8a531
Binary files /dev/null and b/code_backend_theme/static/description/assets/icons/._consultation.png differ
diff --git a/code_backend_theme/static/description/assets/icons/._ecom-black.png b/code_backend_theme/static/description/assets/icons/._ecom-black.png
new file mode 100644
index 0000000..ff71cac
Binary files /dev/null and b/code_backend_theme/static/description/assets/icons/._ecom-black.png differ
diff --git a/code_backend_theme/static/description/assets/icons/._education-black.png b/code_backend_theme/static/description/assets/icons/._education-black.png
new file mode 100644
index 0000000..0387891
Binary files /dev/null and b/code_backend_theme/static/description/assets/icons/._education-black.png differ
diff --git a/code_backend_theme/static/description/assets/icons/._hotel-black.png b/code_backend_theme/static/description/assets/icons/._hotel-black.png
new file mode 100644
index 0000000..962af8b
Binary files /dev/null and b/code_backend_theme/static/description/assets/icons/._hotel-black.png differ
diff --git a/code_backend_theme/static/description/assets/icons/._license.png b/code_backend_theme/static/description/assets/icons/._license.png
new file mode 100644
index 0000000..26ba90f
Binary files /dev/null and b/code_backend_theme/static/description/assets/icons/._license.png differ
diff --git a/code_backend_theme/static/description/assets/icons/._lifebuoy.png b/code_backend_theme/static/description/assets/icons/._lifebuoy.png
new file mode 100644
index 0000000..51bb660
Binary files /dev/null and b/code_backend_theme/static/description/assets/icons/._lifebuoy.png differ
diff --git a/code_backend_theme/static/description/assets/icons/._manufacturing-black.png b/code_backend_theme/static/description/assets/icons/._manufacturing-black.png
new file mode 100644
index 0000000..54bc914
Binary files /dev/null and b/code_backend_theme/static/description/assets/icons/._manufacturing-black.png differ
diff --git a/code_backend_theme/static/description/assets/icons/._pos-black.png b/code_backend_theme/static/description/assets/icons/._pos-black.png
new file mode 100644
index 0000000..a11f4cd
Binary files /dev/null and b/code_backend_theme/static/description/assets/icons/._pos-black.png differ
diff --git a/code_backend_theme/static/description/assets/icons/._puzzle.png b/code_backend_theme/static/description/assets/icons/._puzzle.png
new file mode 100644
index 0000000..f7e7e7e
Binary files /dev/null and b/code_backend_theme/static/description/assets/icons/._puzzle.png differ
diff --git a/code_backend_theme/static/description/assets/icons/._restaurant-black.png b/code_backend_theme/static/description/assets/icons/._restaurant-black.png
new file mode 100644
index 0000000..33ea178
Binary files /dev/null and b/code_backend_theme/static/description/assets/icons/._restaurant-black.png differ
diff --git a/code_backend_theme/static/description/assets/icons/._service-black.png b/code_backend_theme/static/description/assets/icons/._service-black.png
new file mode 100644
index 0000000..0ec2cf2
Binary files /dev/null and b/code_backend_theme/static/description/assets/icons/._service-black.png differ
diff --git a/code_backend_theme/static/description/assets/icons/._trading-black.png b/code_backend_theme/static/description/assets/icons/._trading-black.png
new file mode 100644
index 0000000..d6299d3
Binary files /dev/null and b/code_backend_theme/static/description/assets/icons/._trading-black.png differ
diff --git a/code_backend_theme/static/description/assets/icons/._training.png b/code_backend_theme/static/description/assets/icons/._training.png
new file mode 100644
index 0000000..9bade5f
Binary files /dev/null and b/code_backend_theme/static/description/assets/icons/._training.png differ
diff --git a/code_backend_theme/static/description/assets/icons/._update.png b/code_backend_theme/static/description/assets/icons/._update.png
new file mode 100644
index 0000000..4878483
Binary files /dev/null and b/code_backend_theme/static/description/assets/icons/._update.png differ
diff --git a/code_backend_theme/static/description/assets/icons/._user.png b/code_backend_theme/static/description/assets/icons/._user.png
new file mode 100644
index 0000000..d5b105a
Binary files /dev/null and b/code_backend_theme/static/description/assets/icons/._user.png differ
diff --git a/code_backend_theme/static/description/assets/icons/._wrench.png b/code_backend_theme/static/description/assets/icons/._wrench.png
new file mode 100644
index 0000000..db48ce4
Binary files /dev/null and b/code_backend_theme/static/description/assets/icons/._wrench.png differ
diff --git a/code_backend_theme/static/description/assets/icons/chevron.png b/code_backend_theme/static/description/assets/icons/chevron.png
new file mode 100644
index 0000000..2089293
Binary files /dev/null and b/code_backend_theme/static/description/assets/icons/chevron.png differ
diff --git a/code_backend_theme/static/description/assets/icons/cogs.png b/code_backend_theme/static/description/assets/icons/cogs.png
new file mode 100644
index 0000000..95d0bad
Binary files /dev/null and b/code_backend_theme/static/description/assets/icons/cogs.png differ
diff --git a/code_backend_theme/static/description/assets/icons/consultation.png b/code_backend_theme/static/description/assets/icons/consultation.png
new file mode 100644
index 0000000..8319d4b
Binary files /dev/null and b/code_backend_theme/static/description/assets/icons/consultation.png differ
diff --git a/code_backend_theme/static/description/assets/icons/ecom-black.png b/code_backend_theme/static/description/assets/icons/ecom-black.png
new file mode 100644
index 0000000..a9385ff
Binary files /dev/null and b/code_backend_theme/static/description/assets/icons/ecom-black.png differ
diff --git a/code_backend_theme/static/description/assets/icons/education-black.png b/code_backend_theme/static/description/assets/icons/education-black.png
new file mode 100644
index 0000000..3eb09b2
Binary files /dev/null and b/code_backend_theme/static/description/assets/icons/education-black.png differ
diff --git a/code_backend_theme/static/description/assets/icons/feature-icons/._lifebuoy.png b/code_backend_theme/static/description/assets/icons/feature-icons/._lifebuoy.png
new file mode 100644
index 0000000..4f178d2
Binary files /dev/null and b/code_backend_theme/static/description/assets/icons/feature-icons/._lifebuoy.png differ
diff --git a/code_backend_theme/static/description/assets/icons/feature-icons/document.png b/code_backend_theme/static/description/assets/icons/feature-icons/document.png
new file mode 100644
index 0000000..4054e84
Binary files /dev/null and b/code_backend_theme/static/description/assets/icons/feature-icons/document.png differ
diff --git a/code_backend_theme/static/description/assets/icons/feature-icons/down.png b/code_backend_theme/static/description/assets/icons/feature-icons/down.png
new file mode 100644
index 0000000..65a94a2
Binary files /dev/null and b/code_backend_theme/static/description/assets/icons/feature-icons/down.png differ
diff --git a/code_backend_theme/static/description/assets/icons/feature-icons/lifebuoy.png b/code_backend_theme/static/description/assets/icons/feature-icons/lifebuoy.png
new file mode 100644
index 0000000..658d56c
Binary files /dev/null and b/code_backend_theme/static/description/assets/icons/feature-icons/lifebuoy.png differ
diff --git a/code_backend_theme/static/description/assets/icons/hotel-black.png b/code_backend_theme/static/description/assets/icons/hotel-black.png
new file mode 100644
index 0000000..130f613
Binary files /dev/null and b/code_backend_theme/static/description/assets/icons/hotel-black.png differ
diff --git a/code_backend_theme/static/description/assets/icons/license.png b/code_backend_theme/static/description/assets/icons/license.png
new file mode 100644
index 0000000..a586979
Binary files /dev/null and b/code_backend_theme/static/description/assets/icons/license.png differ
diff --git a/code_backend_theme/static/description/assets/icons/lifebuoy.png b/code_backend_theme/static/description/assets/icons/lifebuoy.png
new file mode 100644
index 0000000..658d56c
Binary files /dev/null and b/code_backend_theme/static/description/assets/icons/lifebuoy.png differ
diff --git a/code_backend_theme/static/description/assets/icons/manufacturing-black.png b/code_backend_theme/static/description/assets/icons/manufacturing-black.png
new file mode 100644
index 0000000..697eb0e
Binary files /dev/null and b/code_backend_theme/static/description/assets/icons/manufacturing-black.png differ
diff --git a/code_backend_theme/static/description/assets/icons/pos-black.png b/code_backend_theme/static/description/assets/icons/pos-black.png
new file mode 100644
index 0000000..97c0f90
Binary files /dev/null and b/code_backend_theme/static/description/assets/icons/pos-black.png differ
diff --git a/code_backend_theme/static/description/assets/icons/puzzle.png b/code_backend_theme/static/description/assets/icons/puzzle.png
new file mode 100644
index 0000000..65cf854
Binary files /dev/null and b/code_backend_theme/static/description/assets/icons/puzzle.png differ
diff --git a/code_backend_theme/static/description/assets/icons/restaurant-black.png b/code_backend_theme/static/description/assets/icons/restaurant-black.png
new file mode 100644
index 0000000..4a35eb9
Binary files /dev/null and b/code_backend_theme/static/description/assets/icons/restaurant-black.png differ
diff --git a/code_backend_theme/static/description/assets/icons/service-black.png b/code_backend_theme/static/description/assets/icons/service-black.png
new file mode 100644
index 0000000..301ab51
Binary files /dev/null and b/code_backend_theme/static/description/assets/icons/service-black.png differ
diff --git a/code_backend_theme/static/description/assets/icons/trading-black.png b/code_backend_theme/static/description/assets/icons/trading-black.png
new file mode 100644
index 0000000..9398ba2
Binary files /dev/null and b/code_backend_theme/static/description/assets/icons/trading-black.png differ
diff --git a/code_backend_theme/static/description/assets/icons/training.png b/code_backend_theme/static/description/assets/icons/training.png
new file mode 100644
index 0000000..884ca02
Binary files /dev/null and b/code_backend_theme/static/description/assets/icons/training.png differ
diff --git a/code_backend_theme/static/description/assets/icons/update.png b/code_backend_theme/static/description/assets/icons/update.png
new file mode 100644
index 0000000..ecbc5a0
Binary files /dev/null and b/code_backend_theme/static/description/assets/icons/update.png differ
diff --git a/code_backend_theme/static/description/assets/icons/user.png b/code_backend_theme/static/description/assets/icons/user.png
new file mode 100644
index 0000000..6ffb23d
Binary files /dev/null and b/code_backend_theme/static/description/assets/icons/user.png differ
diff --git a/code_backend_theme/static/description/assets/icons/wrench.png b/code_backend_theme/static/description/assets/icons/wrench.png
new file mode 100644
index 0000000..6c04dea
Binary files /dev/null and b/code_backend_theme/static/description/assets/icons/wrench.png differ
diff --git a/code_backend_theme/static/description/assets/menu_focus.png b/code_backend_theme/static/description/assets/menu_focus.png
new file mode 100644
index 0000000..713e360
Binary files /dev/null and b/code_backend_theme/static/description/assets/menu_focus.png differ
diff --git a/code_backend_theme/static/description/assets/resp-gif.gif b/code_backend_theme/static/description/assets/resp-gif.gif
new file mode 100644
index 0000000..d543f33
Binary files /dev/null and b/code_backend_theme/static/description/assets/resp-gif.gif differ
diff --git a/code_backend_theme/static/description/assets/responsive.png b/code_backend_theme/static/description/assets/responsive.png
new file mode 100644
index 0000000..fdfe2f6
Binary files /dev/null and b/code_backend_theme/static/description/assets/responsive.png differ
diff --git a/code_backend_theme/static/description/assets/screenshots/alert.png b/code_backend_theme/static/description/assets/screenshots/alert.png
new file mode 100644
index 0000000..71196c7
Binary files /dev/null and b/code_backend_theme/static/description/assets/screenshots/alert.png differ
diff --git a/code_backend_theme/static/description/assets/screenshots/apps_uninstall.png b/code_backend_theme/static/description/assets/screenshots/apps_uninstall.png
new file mode 100644
index 0000000..8ff9ec7
Binary files /dev/null and b/code_backend_theme/static/description/assets/screenshots/apps_uninstall.png differ
diff --git a/code_backend_theme/static/description/assets/screenshots/chatters.png b/code_backend_theme/static/description/assets/screenshots/chatters.png
new file mode 100644
index 0000000..42e6a35
Binary files /dev/null and b/code_backend_theme/static/description/assets/screenshots/chatters.png differ
diff --git a/code_backend_theme/static/description/assets/screenshots/discuss.png b/code_backend_theme/static/description/assets/screenshots/discuss.png
new file mode 100644
index 0000000..abba065
Binary files /dev/null and b/code_backend_theme/static/description/assets/screenshots/discuss.png differ
diff --git a/code_backend_theme/static/description/assets/screenshots/form.png b/code_backend_theme/static/description/assets/screenshots/form.png
new file mode 100644
index 0000000..c5520be
Binary files /dev/null and b/code_backend_theme/static/description/assets/screenshots/form.png differ
diff --git a/code_backend_theme/static/description/assets/screenshots/form_product.png b/code_backend_theme/static/description/assets/screenshots/form_product.png
new file mode 100644
index 0000000..10d2ca7
Binary files /dev/null and b/code_backend_theme/static/description/assets/screenshots/form_product.png differ
diff --git a/code_backend_theme/static/description/assets/screenshots/graph.png b/code_backend_theme/static/description/assets/screenshots/graph.png
new file mode 100644
index 0000000..0d7135c
Binary files /dev/null and b/code_backend_theme/static/description/assets/screenshots/graph.png differ
diff --git a/code_backend_theme/static/description/assets/screenshots/group.png b/code_backend_theme/static/description/assets/screenshots/group.png
new file mode 100644
index 0000000..926afe5
Binary files /dev/null and b/code_backend_theme/static/description/assets/screenshots/group.png differ
diff --git a/code_backend_theme/static/description/assets/screenshots/invoice.png b/code_backend_theme/static/description/assets/screenshots/invoice.png
new file mode 100644
index 0000000..8a5e13e
Binary files /dev/null and b/code_backend_theme/static/description/assets/screenshots/invoice.png differ
diff --git a/code_backend_theme/static/description/assets/screenshots/kanban_empl.png b/code_backend_theme/static/description/assets/screenshots/kanban_empl.png
new file mode 100644
index 0000000..61d4423
Binary files /dev/null and b/code_backend_theme/static/description/assets/screenshots/kanban_empl.png differ
diff --git a/code_backend_theme/static/description/assets/screenshots/kanban_group.png b/code_backend_theme/static/description/assets/screenshots/kanban_group.png
new file mode 100644
index 0000000..4d04525
Binary files /dev/null and b/code_backend_theme/static/description/assets/screenshots/kanban_group.png differ
diff --git a/code_backend_theme/static/description/assets/screenshots/kanban_product.png b/code_backend_theme/static/description/assets/screenshots/kanban_product.png
new file mode 100644
index 0000000..fe95a1d
Binary files /dev/null and b/code_backend_theme/static/description/assets/screenshots/kanban_product.png differ
diff --git a/code_backend_theme/static/description/assets/screenshots/kanban_recruits.png b/code_backend_theme/static/description/assets/screenshots/kanban_recruits.png
new file mode 100644
index 0000000..25d2132
Binary files /dev/null and b/code_backend_theme/static/description/assets/screenshots/kanban_recruits.png differ
diff --git a/code_backend_theme/static/description/assets/screenshots/kanban_sale.png b/code_backend_theme/static/description/assets/screenshots/kanban_sale.png
new file mode 100644
index 0000000..de2e9ba
Binary files /dev/null and b/code_backend_theme/static/description/assets/screenshots/kanban_sale.png differ
diff --git a/code_backend_theme/static/description/assets/screenshots/kiosk.png b/code_backend_theme/static/description/assets/screenshots/kiosk.png
new file mode 100644
index 0000000..34ac29f
Binary files /dev/null and b/code_backend_theme/static/description/assets/screenshots/kiosk.png differ
diff --git a/code_backend_theme/static/description/assets/screenshots/list_purchase.png b/code_backend_theme/static/description/assets/screenshots/list_purchase.png
new file mode 100644
index 0000000..e46b5d7
Binary files /dev/null and b/code_backend_theme/static/description/assets/screenshots/list_purchase.png differ
diff --git a/code_backend_theme/static/description/assets/screenshots/list_sales.png b/code_backend_theme/static/description/assets/screenshots/list_sales.png
new file mode 100644
index 0000000..bb852c2
Binary files /dev/null and b/code_backend_theme/static/description/assets/screenshots/list_sales.png differ
diff --git a/code_backend_theme/static/description/assets/screenshots/login.png b/code_backend_theme/static/description/assets/screenshots/login.png
new file mode 100644
index 0000000..cb6e824
Binary files /dev/null and b/code_backend_theme/static/description/assets/screenshots/login.png differ
diff --git a/code_backend_theme/static/description/assets/screenshots/modal.png b/code_backend_theme/static/description/assets/screenshots/modal.png
new file mode 100644
index 0000000..b8fd4ce
Binary files /dev/null and b/code_backend_theme/static/description/assets/screenshots/modal.png differ
diff --git a/code_backend_theme/static/description/assets/screenshots/settings.png b/code_backend_theme/static/description/assets/screenshots/settings.png
new file mode 100644
index 0000000..f8d344c
Binary files /dev/null and b/code_backend_theme/static/description/assets/screenshots/settings.png differ
diff --git a/code_backend_theme/static/description/assets/screenshots/sidebar-gif.gif b/code_backend_theme/static/description/assets/screenshots/sidebar-gif.gif
new file mode 100644
index 0000000..072bc82
Binary files /dev/null and b/code_backend_theme/static/description/assets/screenshots/sidebar-gif.gif differ
diff --git a/code_backend_theme/static/description/assets/screenshots/sidebar_list.png b/code_backend_theme/static/description/assets/screenshots/sidebar_list.png
new file mode 100644
index 0000000..a6b7e0e
Binary files /dev/null and b/code_backend_theme/static/description/assets/screenshots/sidebar_list.png differ
diff --git a/code_backend_theme/static/description/assets/screenshots/sidebar_settings.png b/code_backend_theme/static/description/assets/screenshots/sidebar_settings.png
new file mode 100644
index 0000000..3dc7c28
Binary files /dev/null and b/code_backend_theme/static/description/assets/screenshots/sidebar_settings.png differ
diff --git a/code_backend_theme/static/description/assets/screenshots/tab.png b/code_backend_theme/static/description/assets/screenshots/tab.png
new file mode 100644
index 0000000..de07e4a
Binary files /dev/null and b/code_backend_theme/static/description/assets/screenshots/tab.png differ
diff --git a/code_backend_theme/static/description/banner.png b/code_backend_theme/static/description/banner.png
new file mode 100644
index 0000000..dad06e9
Binary files /dev/null and b/code_backend_theme/static/description/banner.png differ
diff --git a/code_backend_theme/static/description/icon.png b/code_backend_theme/static/description/icon.png
new file mode 100644
index 0000000..d620656
Binary files /dev/null and b/code_backend_theme/static/description/icon.png differ
diff --git a/code_backend_theme/static/description/index.html b/code_backend_theme/static/description/index.html
new file mode 100644
index 0000000..d21044e
--- /dev/null
+++ b/code_backend_theme/static/description/index.html
@@ -0,0 +1,1004 @@
+
+
+
+
+
+ Code Backend Theme
+
+
Minimalist and Elegant Backend
+ Theme for Odoo 14
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The Code Backend Theme V14 Gives You a Fully Modified View with a Full Screen Display.
+ This is a Minimalist and Elegant Backend Theme for Odoo 14.
+ This Theme Will Change Your Old Experience to a New Experience With Odoo.
+ It is a Perfect Choice for Your Odoo Backend and an Attractive Theme for Your Odoo 14.
+ It will Give You a Clean Layout with a New Color Combination and a Modified Font. It has a
+ Sidebar with
+ New App Icons and Company Logo. This Will Change Your Old Kanban, List and Form Views to A Fully
+ Modified View.
+
+
+
+
+ Please make sure that you install
+ all
+ your apps prior to the installation of this theme.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ New
+
+
Fully Responsive Layout
+
+ Now take advantage of everything your dashboard has to offer even on the go. Our design are
+ now
+ fully responsive enabling you to view and manage everything from the comfort of your mobile
+ device. Everything
+ has been designed in a meticulous fashion so that every view snaps itself to fit the size of
+ the
+ device you are using, be it smartphones, tablet or any other portables, our theme adjusts
+ itself
+ to fit the screen size.
+
+
+
+ Fully responsive
+
+
+
+
+ Fly-out hamburger menu on the left
+
+
+
+
+ Fits perfectly to all screen sizes
+
+
+
+
+ Quick access menu at the bottom in discuss
+
+
+
+
+
+
+
+
+
+
+
+
+
Kanban Group View
+
+ The Code Backend Theme V14 Gives You a Fully Modified Kanban View and Kanban Group View.
+ The Section Wise Separated Stages give a Pleasant Experience And an Extraordinary Design
+ To Your Content Tiles Making The Tiles Look Great.
+ It will Give You a Clean Layout with the New Color Combination and a Modified Font.
+
+
+
+
+
+ Modified Font
+
+
+
+
+ New Color Combination
+
+
+
+
+ Full Screen View
+
+
+
+
+
+
+ Stages are Separated in View
+
+
+
+
+ Clean Layout
+
+
+
+
+ Buttons with New Colors
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
List View
+
+ The All new Code Backend Theme V14 Gives You The Fully Modified List View and This Table Design
+ is Also Have Awesome Design and it Gives You More Beauty for Your Odoo Backend.
+ It will Give You a Clean Layout with the New Color Combination and a Modified Font.
+
+
+
+
+
+ Modified Table Style
+
+
+
+
+ New Color Combination
+
+
+
+
+ New Scroll Bar
+
+
+
+
+
+
+ New Status Tag
+
+
+
+
+ New Scrollbar
+
+
+
+
+ Buttons with New Colors
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Form View
+
+ Code Backend Theme Gives You The Fully Modified Form View with a Full Screen Experience. It will
+ Give You a Clean Layout with the New Color Combination
+ and a Modified Font.
+
+
+
+
+
+ Modified Form Style
+
+
+
+
+ Full Screen Form View
+
+
+
+
+ New Looks for Tabs
+
+
+
+
+
+
+ New Style for Required Field
+
+
+
+
+ New Chatter Style Under Form View
+
+
+
+
+ New Looks for Status Button
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Overview
+
+ Code Backend Theme V14 is an Attractive Theme for Your Odoo 14.
+ This Theme Will Change Improve Your Experience With Odoo.
+ This is a Minimalist and Elegant Backend Theme for Odoo 14 And Can Offer a Perfect Choice
+ for
+ Your Odoo Backend.
+
+
+
+
+ Modified Structure for All Type Views
+
+
+
+
+ New Style for Active Menus, Radio Buttons and Checkboxes
+
+
+
+ New Color Combination
+
+
+
+
+ New Look for All Applications
+
+
+
+ A Clean layout and New Font Style
+
+
+
+ Sidebar with New Menu Icons
+
+
+
+
+
+
+
+
+
+
All-New Menu Design
+
+ The All-New Menu Design is Main Attractive Section for the Code Backend Theme. The Sidebar
+ have New Minimalist
+ Icons for Applications in Odoo. Also the Sidebar Have Closing and Opening Option.
+ Customisable Logo Attached in Sidebar
+ That is Automatically Fetch Your Company Logo.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Easily Access Sidebar Menu
+
+ Reveal the sidebar menu with just a click. Sidebar menu features all the relevant links to
+ navigate
+ through the application.
+ Hiding the sidebar leaves more space on the main area offering a distraction-free view that lets
+ you
+ focus on what matters the most.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
2
+
+
Group By View
+
+
+
+
+
+
+
+
+
+
+
+
3
+
+
Settings Page
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
5
+
+
Product Kanban View
+
+
+
+
+
+
+
+
+
+
+
+
6
+
+
Purchase List View
+
+
+
+
+
+
+
+
+
+
+
+
7
+
+
Product View with Smart Buttons
+
+
+
+
+
+
+
+
+
+
+
8
+
+
Modified Alert Notifications are Placed on the Right Bottom of Display
+
+
+
+
+
+
+
+
+
+
+
+
+
9
+
+
Wizards and User Error Popups
+
+
+
+
+
+
+
+
+
+
+
+
10
+
+
New Looks for The Tabs
+
+
+
+
+
+
+
+
+
+
+
+
11
+
+
Recruitment Kanban View With Ribbons
+
+
+
+
+
+
+
+
+
+
+
12
+
+
Sales Kanban View
+
+
+
+
+
+
+
+
+
+
+
+
13
+
+
Modified Kanban View for Employees With New Designed Category Section
+
+
+
+
+
+
+
+
+
+
+
+
14
+
+
Newly Customised Chatter and Popup Chatter
+
+
+
+
+
+
+
+
+
+
+
15
+
+
New Looks for Wizards and Buttons with New Colors
+
+
+
+
+
+
+
+
+
+
+
16
+
+
Sidebar with List View
+
+
+
+
+
+
+
+
+
+
+
+
17
+
+
Sidebar with Settings Page View
+
+
+
+
+
+
+
+
+
+
+
+
18
+
+
Attendance Pages
+
+
+
+
+
+
+
+
+
+
+
+
19
+
+
Invoice Pages
+
+
+
+
+
+
+
+
+
+
+
+
20
+
+
Graphs with Sidebar
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Our Services
+
+
+
+
+
+
+
+ Odoo
+ Customization
+
+
+
+
+
+
+
+ Odoo
+ Implementation
+
+
+
+
+
+
+
+ Odoo
+ Support
+
+
+
+
+
+
+
+ Hire
+ Odoo
+ Developer
+
+
+
+
+
+
+
+ Odoo
+ Integration
+
+
+
+
+
+
+
+ Odoo
+ Migration
+
+
+
+
+
+
+
+ Odoo
+ Consultancy
+
+
+
+
+
+
+
+ Odoo
+ Implementation
+
+
+
+
+
+
+
+ Odoo
+ Licensing Consultancy
+
+
+
+
+
+
+
+
+
+
+
+ Our Industries
+
+
+
+
+
+
+ Trading
+
+
Easily
+ procure
+ and
+ sell your products
+
+
+
+
+
+
+
+ POS
+
+
Easy
+ configuration
+ and convivial experience
+
+
+
+
+
+
+
+ Education
+
+
A
+ platform for
+ educational management
+
+
+
+
+
+
+
+ Manufacturing
+
+
Plan,
+ track and
+ schedule your operations
+
+
+
+
+
+
+ E-commerce & Website
+
+
Mobile
+ friendly,
+ awe-inspiring product pages
+
+
+
+
+
+
+ Service Management
+
+
Keep
+ track of
+ services and invoice
+
+
+
+
+
+
+ Restaurant
+
+
Run
+ your bar or
+ restaurant methodically
+
+
+
+
+
+
+ Hotel Management
+
+
An
+ all-inclusive
+ hotel management application
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/code_backend_theme/static/description/theme_screenshot.png b/code_backend_theme/static/description/theme_screenshot.png
new file mode 100644
index 0000000..47ea6ac
Binary files /dev/null and b/code_backend_theme/static/description/theme_screenshot.png differ
diff --git a/code_backend_theme/static/src/img/code_logo.png b/code_backend_theme/static/src/img/code_logo.png
new file mode 100644
index 0000000..124152a
Binary files /dev/null and b/code_backend_theme/static/src/img/code_logo.png differ
diff --git a/code_backend_theme/static/src/img/icons/Attendances.png b/code_backend_theme/static/src/img/icons/Attendances.png
new file mode 100644
index 0000000..6f2e83d
Binary files /dev/null and b/code_backend_theme/static/src/img/icons/Attendances.png differ
diff --git a/code_backend_theme/static/src/img/icons/CRM.png b/code_backend_theme/static/src/img/icons/CRM.png
new file mode 100644
index 0000000..01e3261
Binary files /dev/null and b/code_backend_theme/static/src/img/icons/CRM.png differ
diff --git a/code_backend_theme/static/src/img/icons/Calendar.png b/code_backend_theme/static/src/img/icons/Calendar.png
new file mode 100644
index 0000000..bfa7e47
Binary files /dev/null and b/code_backend_theme/static/src/img/icons/Calendar.png differ
diff --git a/code_backend_theme/static/src/img/icons/Contacts.png b/code_backend_theme/static/src/img/icons/Contacts.png
new file mode 100644
index 0000000..5865350
Binary files /dev/null and b/code_backend_theme/static/src/img/icons/Contacts.png differ
diff --git a/code_backend_theme/static/src/img/icons/Dashboards.png b/code_backend_theme/static/src/img/icons/Dashboards.png
new file mode 100644
index 0000000..0ab4196
Binary files /dev/null and b/code_backend_theme/static/src/img/icons/Dashboards.png differ
diff --git a/code_backend_theme/static/src/img/icons/Email Marketing.png b/code_backend_theme/static/src/img/icons/Email Marketing.png
new file mode 100644
index 0000000..66c873a
Binary files /dev/null and b/code_backend_theme/static/src/img/icons/Email Marketing.png differ
diff --git a/code_backend_theme/static/src/img/icons/Employees.png b/code_backend_theme/static/src/img/icons/Employees.png
new file mode 100644
index 0000000..85aff52
Binary files /dev/null and b/code_backend_theme/static/src/img/icons/Employees.png differ
diff --git a/code_backend_theme/static/src/img/icons/Events.png b/code_backend_theme/static/src/img/icons/Events.png
new file mode 100644
index 0000000..b0c5e71
Binary files /dev/null and b/code_backend_theme/static/src/img/icons/Events.png differ
diff --git a/code_backend_theme/static/src/img/icons/Expenses.png b/code_backend_theme/static/src/img/icons/Expenses.png
new file mode 100644
index 0000000..67406dd
Binary files /dev/null and b/code_backend_theme/static/src/img/icons/Expenses.png differ
diff --git a/code_backend_theme/static/src/img/icons/Fleet.png b/code_backend_theme/static/src/img/icons/Fleet.png
new file mode 100644
index 0000000..422959b
Binary files /dev/null and b/code_backend_theme/static/src/img/icons/Fleet.png differ
diff --git a/code_backend_theme/static/src/img/icons/Inventory.png b/code_backend_theme/static/src/img/icons/Inventory.png
new file mode 100644
index 0000000..5dd73dd
Binary files /dev/null and b/code_backend_theme/static/src/img/icons/Inventory.png differ
diff --git a/code_backend_theme/static/src/img/icons/Invoicing.png b/code_backend_theme/static/src/img/icons/Invoicing.png
new file mode 100644
index 0000000..9be39f5
Binary files /dev/null and b/code_backend_theme/static/src/img/icons/Invoicing.png differ
diff --git a/code_backend_theme/static/src/img/icons/Link Tracker.png b/code_backend_theme/static/src/img/icons/Link Tracker.png
new file mode 100644
index 0000000..b468d30
Binary files /dev/null and b/code_backend_theme/static/src/img/icons/Link Tracker.png differ
diff --git a/code_backend_theme/static/src/img/icons/Live Chat.png b/code_backend_theme/static/src/img/icons/Live Chat.png
new file mode 100644
index 0000000..60a44e7
Binary files /dev/null and b/code_backend_theme/static/src/img/icons/Live Chat.png differ
diff --git a/code_backend_theme/static/src/img/icons/Lunch.png b/code_backend_theme/static/src/img/icons/Lunch.png
new file mode 100644
index 0000000..d8a2e95
Binary files /dev/null and b/code_backend_theme/static/src/img/icons/Lunch.png differ
diff --git a/code_backend_theme/static/src/img/icons/Maintenance.png b/code_backend_theme/static/src/img/icons/Maintenance.png
new file mode 100644
index 0000000..a0bb8a7
Binary files /dev/null and b/code_backend_theme/static/src/img/icons/Maintenance.png differ
diff --git a/code_backend_theme/static/src/img/icons/Manufacturing.png b/code_backend_theme/static/src/img/icons/Manufacturing.png
new file mode 100644
index 0000000..4b922f9
Binary files /dev/null and b/code_backend_theme/static/src/img/icons/Manufacturing.png differ
diff --git a/code_backend_theme/static/src/img/icons/Members.png b/code_backend_theme/static/src/img/icons/Members.png
new file mode 100644
index 0000000..c538782
Binary files /dev/null and b/code_backend_theme/static/src/img/icons/Members.png differ
diff --git a/code_backend_theme/static/src/img/icons/Note.png b/code_backend_theme/static/src/img/icons/Note.png
new file mode 100644
index 0000000..329f473
Binary files /dev/null and b/code_backend_theme/static/src/img/icons/Note.png differ
diff --git a/code_backend_theme/static/src/img/icons/Point of Sale.png b/code_backend_theme/static/src/img/icons/Point of Sale.png
new file mode 100644
index 0000000..bbdb5a1
Binary files /dev/null and b/code_backend_theme/static/src/img/icons/Point of Sale.png differ
diff --git a/code_backend_theme/static/src/img/icons/Project.png b/code_backend_theme/static/src/img/icons/Project.png
new file mode 100644
index 0000000..c22fe19
Binary files /dev/null and b/code_backend_theme/static/src/img/icons/Project.png differ
diff --git a/code_backend_theme/static/src/img/icons/Purchase.png b/code_backend_theme/static/src/img/icons/Purchase.png
new file mode 100644
index 0000000..457740d
Binary files /dev/null and b/code_backend_theme/static/src/img/icons/Purchase.png differ
diff --git a/code_backend_theme/static/src/img/icons/Recruitment.png b/code_backend_theme/static/src/img/icons/Recruitment.png
new file mode 100644
index 0000000..b3a2dc7
Binary files /dev/null and b/code_backend_theme/static/src/img/icons/Recruitment.png differ
diff --git a/code_backend_theme/static/src/img/icons/Repairs.png b/code_backend_theme/static/src/img/icons/Repairs.png
new file mode 100644
index 0000000..0547711
Binary files /dev/null and b/code_backend_theme/static/src/img/icons/Repairs.png differ
diff --git a/code_backend_theme/static/src/img/icons/SMS Marketing.png b/code_backend_theme/static/src/img/icons/SMS Marketing.png
new file mode 100644
index 0000000..6b90e20
Binary files /dev/null and b/code_backend_theme/static/src/img/icons/SMS Marketing.png differ
diff --git a/code_backend_theme/static/src/img/icons/Sales.png b/code_backend_theme/static/src/img/icons/Sales.png
new file mode 100644
index 0000000..6259ec7
Binary files /dev/null and b/code_backend_theme/static/src/img/icons/Sales.png differ
diff --git a/code_backend_theme/static/src/img/icons/Surveys.png b/code_backend_theme/static/src/img/icons/Surveys.png
new file mode 100644
index 0000000..f422f46
Binary files /dev/null and b/code_backend_theme/static/src/img/icons/Surveys.png differ
diff --git a/code_backend_theme/static/src/img/icons/Time Off.png b/code_backend_theme/static/src/img/icons/Time Off.png
new file mode 100644
index 0000000..c34cde4
Binary files /dev/null and b/code_backend_theme/static/src/img/icons/Time Off.png differ
diff --git a/code_backend_theme/static/src/img/icons/Timesheets.png b/code_backend_theme/static/src/img/icons/Timesheets.png
new file mode 100644
index 0000000..3c552b3
Binary files /dev/null and b/code_backend_theme/static/src/img/icons/Timesheets.png differ
diff --git a/code_backend_theme/static/src/img/icons/Website.png b/code_backend_theme/static/src/img/icons/Website.png
new file mode 100644
index 0000000..cd10570
Binary files /dev/null and b/code_backend_theme/static/src/img/icons/Website.png differ
diff --git a/code_backend_theme/static/src/img/icons/apps.png b/code_backend_theme/static/src/img/icons/apps.png
new file mode 100644
index 0000000..ce5cf33
Binary files /dev/null and b/code_backend_theme/static/src/img/icons/apps.png differ
diff --git a/code_backend_theme/static/src/img/icons/close.png b/code_backend_theme/static/src/img/icons/close.png
new file mode 100644
index 0000000..c6ea25f
Binary files /dev/null and b/code_backend_theme/static/src/img/icons/close.png differ
diff --git a/code_backend_theme/static/src/img/icons/discuss.png b/code_backend_theme/static/src/img/icons/discuss.png
new file mode 100644
index 0000000..382b72f
Binary files /dev/null and b/code_backend_theme/static/src/img/icons/discuss.png differ
diff --git a/code_backend_theme/static/src/img/icons/eLearning.png b/code_backend_theme/static/src/img/icons/eLearning.png
new file mode 100644
index 0000000..e0cd5c2
Binary files /dev/null and b/code_backend_theme/static/src/img/icons/eLearning.png differ
diff --git a/code_backend_theme/static/src/img/icons/settings.png b/code_backend_theme/static/src/img/icons/settings.png
new file mode 100644
index 0000000..7ff68e4
Binary files /dev/null and b/code_backend_theme/static/src/img/icons/settings.png differ
diff --git a/code_backend_theme/static/src/js/chrome/sidebar.js b/code_backend_theme/static/src/js/chrome/sidebar.js
new file mode 100644
index 0000000..6825eb3
--- /dev/null
+++ b/code_backend_theme/static/src/js/chrome/sidebar.js
@@ -0,0 +1,32 @@
+/** @odoo-module **/
+
+import { Component } from "@odoo/owl";
+import { patch } from "@web/core/utils/patch";
+import { AppMenu } from "@web/webclient/app_menu/app_menu";
+
+export class SideBar extends Component {
+ setup() {
+ this.apps = this.props.menuData.children.map((app) => ({
+ actionID: parseInt(app.action.split(",")[1]),
+ menuID: app.id,
+ name: app.name,
+ xmlID: app.xmlid,
+ web_icon_data: app.web_icon_data,
+ }));
+ }
+
+ onAppClick(app) {
+ this.env.bus.trigger("APP-CLICKED", {
+ action_id: app.actionID,
+ menu_id: app.menuID,
+ });
+ }
+}
+SideBar.template = "code_backend_theme.Sidebar";
+
+// Patch AppMenu to include the sidebar
+patch(AppMenu.prototype, "code_backend_theme.Sidebar", {
+ setup() {
+ super.setup();
+ },
+});
diff --git a/code_backend_theme/static/src/js/chrome/sidebar_menu.js b/code_backend_theme/static/src/js/chrome/sidebar_menu.js
new file mode 100644
index 0000000..ea63fad
--- /dev/null
+++ b/code_backend_theme/static/src/js/chrome/sidebar_menu.js
@@ -0,0 +1,15 @@
+/** @odoo-module **/
+
+import { patch } from "@web/core/utils/patch";
+import { AppMenu } from "@web/webclient/app_menu/app_menu";
+
+patch(AppMenu.prototype, "code_backend_theme.SidebarMenu", {
+ setup() {
+ super.setup();
+ this.state = { sidebarOpen: false };
+ },
+
+ toggleSidebar() {
+ this.state.sidebarOpen = !this.state.sidebarOpen;
+ },
+});
diff --git a/code_backend_theme/static/src/js/fields/basic_fields.js b/code_backend_theme/static/src/js/fields/basic_fields.js
new file mode 100644
index 0000000..e525bf4
--- /dev/null
+++ b/code_backend_theme/static/src/js/fields/basic_fields.js
@@ -0,0 +1,57 @@
+/** @odoo-module **/
+
+import { patch } from "@web/core/utils/patch";
+import { ChartRenderer } from "@web/views/graph/chart_renderer"; // ✅ new graph renderer
+import { Chart } from "web.chartjs"; // ✅ Chart.js must be imported explicitly
+
+patch(ChartRenderer.prototype, "code_backend_theme.fields", {
+ _getBarChartConfig() {
+ const data = [];
+ const labels = [];
+ const backgroundColor = [];
+
+ this.props.data[0].values.forEach((pt) => {
+ data.push(pt.value);
+ labels.push(pt.label);
+ const color =
+ pt.type === "past"
+ ? "#ccbdc8"
+ : pt.type === "future"
+ ? "#f1b44c"
+ : "#556ee6";
+ backgroundColor.push(color);
+ });
+
+ return {
+ type: "bar",
+ data: {
+ labels,
+ datasets: [
+ {
+ data,
+ fill: "start",
+ label: this.props.data[0].key,
+ backgroundColor,
+ },
+ ],
+ },
+ options: {
+ plugins: {
+ legend: { display: false },
+ tooltip: {
+ intersect: false,
+ position: "nearest",
+ caretSize: 0,
+ },
+ },
+ scales: {
+ y: { display: false }, // ✅ new Chart.js v3+ syntax
+ },
+ maintainAspectRatio: false,
+ elements: {
+ line: { tension: 0.000001 },
+ },
+ },
+ };
+ },
+});
diff --git a/code_backend_theme/static/src/js/fields/graph.js b/code_backend_theme/static/src/js/fields/graph.js
new file mode 100644
index 0000000..64a7594
--- /dev/null
+++ b/code_backend_theme/static/src/js/fields/graph.js
@@ -0,0 +1,82 @@
+/** @odoo-module **/
+
+import { patch } from "@web/core/utils/patch";
+import { GraphRenderer } from "@web/views/graph/graph_renderer";
+import { Chart } from "web.chartjs";
+
+const MyCOLORS = [
+ "#556ee6", "#f1b44c", "#50a5f1", "#ffbb78", "#34c38f", "#98df8a", "#d62728",
+ "#ff9896", "#9467bd", "#c5b0d5", "#8c564b", "#c49c94", "#e377c2", "#f7b6d2",
+ "#7f7f7f", "#c7c7c7", "#bcbd22", "#dbdb8d", "#17becf", "#9edae5"
+];
+const MyCOLOR_NB = MyCOLORS.length;
+
+function hexToRGBA(hex, opacity) {
+ const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
+ const rgb = result.slice(1, 4).map((n) => parseInt(n, 16)).join(",");
+ return `rgba(${rgb},${opacity})`;
+}
+
+patch(GraphRenderer.prototype, "code_backend_theme.graph", {
+ _getMyColor(index) {
+ return MyCOLORS[index % MyCOLOR_NB];
+ },
+
+ _renderBarChart(dataPoints) {
+ const data = this._prepareData(dataPoints);
+ data.datasets.forEach((dataset, index) => {
+ dataset.stack = this.state.stacked ? this.state.origins[dataset.originIndex] : undefined;
+ dataset.backgroundColor = this._getMyColor(index);
+ });
+
+ const options = this._prepareOptions(data.datasets.length);
+ const ctx = document.getElementById(this.chartId);
+ this.chart = new Chart(ctx, {
+ type: "bar",
+ data,
+ options,
+ });
+ },
+
+ _renderLineChart(dataPoints) {
+ const data = this._prepareData(dataPoints);
+ data.datasets.forEach((dataset, index) => {
+ if (this.state.processedGroupBy.length <= 1 && this.state.origins.length > 1) {
+ if (dataset.originIndex === 0) {
+ dataset.fill = "origin";
+ dataset.backgroundColor = hexToRGBA(MyCOLORS[0], 0.4);
+ dataset.borderColor = hexToRGBA(MyCOLORS[0], 1);
+ } else if (dataset.originIndex === 1) {
+ dataset.borderColor = hexToRGBA(MyCOLORS[1], 1);
+ } else {
+ dataset.borderColor = this._getMyColor(index);
+ }
+ } else {
+ dataset.borderColor = this._getMyColor(index);
+ }
+ if (data.labels.length === 1) {
+ dataset.data.unshift(undefined);
+ }
+ dataset.pointBackgroundColor = dataset.borderColor;
+ dataset.pointBorderColor = "rgba(0,0,0,0.2)";
+ });
+
+ if (data.datasets.length === 1) {
+ const dataset = data.datasets[0];
+ dataset.fill = "origin";
+ dataset.backgroundColor = hexToRGBA(MyCOLORS[0], 0.4);
+ }
+
+ data.labels = data.labels.length > 1
+ ? data.labels
+ : [].concat([[[""]]], data.labels, [[[""]]]);
+
+ const options = this._prepareOptions(data.datasets.length);
+ const ctx = document.getElementById(this.chartId);
+ this.chart = new Chart(ctx, {
+ type: "line",
+ data,
+ options,
+ });
+ },
+});
diff --git a/code_backend_theme/static/src/scss/datetimepicker.scss b/code_backend_theme/static/src/scss/datetimepicker.scss
new file mode 100644
index 0000000..422bc75
--- /dev/null
+++ b/code_backend_theme/static/src/scss/datetimepicker.scss
@@ -0,0 +1,92 @@
+/* SCSS Variables (assumed to be defined in the project) */
+$primary_accent: #556ee6 !default;
+$inverse_accent: #ffffff !default;
+$btn-transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
+
+/* Bootstrap Datepicker */
+.o-datepicker .table-sm {
+ > thead {
+ > tr > .prev {
+ color: $inverse_accent !important;
+ background-color: $primary_accent !important;
+ &:hover {
+ background-color: darken($primary_accent, 10%) !important;
+ }
+ > .fa {
+ color: $inverse_accent !important;
+ }
+ }
+ > tr > .next {
+ color: $inverse_accent !important;
+ background-color: $primary_accent !important;
+ &:hover {
+ background-color: darken($primary_accent, 10%) !important;
+ }
+ > .fa {
+ color: $inverse_accent !important;
+ }
+ }
+ > tr > .picker-switch {
+ color: $inverse_accent !important;
+ background-color: $primary_accent !important;
+ &:hover {
+ background-color: darken($primary_accent, 10%) !important;
+ }
+ }
+ }
+ > tbody > tr > td {
+ &.today::before {
+ border-bottom-color: $primary_accent !important;
+ }
+ &.active {
+ background-color: $primary_accent !important;
+ color: $inverse_accent !important;
+ }
+ }
+}
+
+.picker-switch {
+ span.fa {
+ margin: 0;
+ transition: $btn-transition;
+ &.primary {
+ background-color: $primary_accent;
+ color: $inverse_accent;
+ &:hover {
+ background-color: darken($primary_accent, 20%);
+ }
+ }
+ }
+}
+
+/* Daterangepicker */
+.daterangepicker .drp-calendar .calendar-table thead tr:first-child {
+ color: $inverse_accent;
+ background-color: $primary_accent;
+}
+
+.daterangepicker .drp-calendar .calendar-table tbody tr td:not(.off).active,
+.daterangepicker .drp-calendar .calendar-table tbody tr td:not(.off).active:hover {
+ background-color: $primary_accent;
+ color: $inverse_accent !important;
+}
+
+.daterangepicker .drp-calendar .calendar-table thead tr:first-child th.prev:hover,
+.daterangepicker .drp-calendar .calendar-table thead tr:first-child th.next:hover {
+ background-color: darken($primary_accent, 20%);
+}
+
+/* Responsive Adjustments */
+@media (max-width: 576px) {
+ .o-datepicker .table-sm {
+ font-size: 12px;
+ }
+
+ .daterangepicker .drp-calendar .calendar-table {
+ font-size: 12px;
+ }
+
+ .picker-switch {
+ font-size: 14px;
+ }
+}
\ No newline at end of file
diff --git a/code_backend_theme/static/src/scss/login.scss b/code_backend_theme/static/src/scss/login.scss
new file mode 100644
index 0000000..524313f
--- /dev/null
+++ b/code_backend_theme/static/src/scss/login.scss
@@ -0,0 +1,194 @@
+/* SCSS Variables (assumed to be defined in the project) */
+$primary_accent: #556ee6 !default;
+$secondary_accent: #334332 !default;
+$inverse_accent: #ffffff !default;
+$bg_white: #ffffff !default;
+$primary_hover: #485ec4 !default;
+
+/* Main Container */
+#wrapwrap > main {
+ background: #f8f8fb;
+}
+
+/* Navbar */
+.navbar {
+ background: $bg_white !important;
+}
+
+/* Body */
+body {
+ font-family: 'Poppins', sans-serif !important;
+}
+
+body.bg-100 {
+ background-color: #f8f8fb !important;
+}
+
+/* Database List Card */
+.card.o-database-list {
+ align-items: center;
+ max-width: 450px !important;
+}
+
+.card.o-database-list .card-body {
+ background-color: $bg_white !important;
+ border-radius: 5px !important;
+ box-shadow: 0 0.75rem 1.5rem rgba(18, 38, 63, 0.03) !important;
+ width: 450px;
+}
+
+/* Links */
+a {
+ color: $primary_accent;
+ text-decoration: none;
+}
+
+a:hover {
+ color: #4458b8;
+ text-decoration: underline;
+}
+
+/* Alerts */
+.alert-info {
+ color: #306391;
+ background-color: #dcedfc;
+ border-color: #cbe4fb;
+}
+
+/* Login Form Button Links */
+.o-login-form button.btn-link {
+ color: #495057;
+ font-weight: 500;
+ font-size: 14px !important;
+}
+
+.o-login-form button.btn-link:hover {
+ color: #171a1c;
+}
+
+/* Login Buttons */
+.btn-primary {
+ color: $inverse_accent;
+ background-color: $primary_accent;
+ border-color: $primary_accent;
+}
+
+.btn-primary:hover {
+ color: $inverse_accent;
+ background-color: $primary_hover;
+ border-color: #4458b8;
+}
+
+.btn-check:active + .btn-primary,
+.btn-check:checked + .btn-primary,
+.btn-primary.active,
+.btn-primary:active,
+.show > .btn-primary.dropdown-toggle {
+ color: $inverse_accent;
+ background-color: #4458b8 !important;
+ border-color: #4053ad !important;
+}
+
+.btn-check:focus + .btn-primary,
+.btn-primary:focus {
+ color: $inverse_accent;
+ background-color: $primary_hover !important;
+ border-color: #4458b8 !important;
+ box-shadow: 0 0 0 0.15rem rgba(111, 132, 234, 0.5) !important;
+}
+
+.o-login-form .btn {
+ display: inline-block;
+ cursor: pointer;
+ user-select: none;
+ padding: 0.47rem 0.75rem;
+ border-radius: 0.25rem;
+ transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
+}
+
+.btn-secondary {
+ color: $inverse_accent !important;
+ background-color: #74788d !important;
+ border-color: #74788d !important;
+}
+
+.btn-secondary:hover {
+ color: $inverse_accent !important;
+ background-color: #636678 !important;
+ border-color: #5d6071 !important;
+}
+
+.btn-secondary:active {
+ color: $inverse_accent;
+ background-color: #5d6071 !important;
+ border-color: #575a6a !important;
+}
+
+.btn-secondary i,
+.btn-secondary span {
+ color: $inverse_accent !important;
+}
+
+.btn-fill-secondary:focus,
+.btn-secondary:focus,
+.btn-fill-secondary.focus,
+.focus.btn-secondary {
+ box-shadow: none !important;
+}
+
+/* Input Fields */
+.o-login-form input {
+ display: block;
+ width: 100%;
+ height: 40px !important;
+ padding: 10px 20px;
+ font-size: 13px;
+ font-weight: 400;
+ line-height: 1.5;
+ color: #495057;
+ background-color: $bg_white;
+ background-clip: padding-box;
+ border: 1px solid #ced4da !important;
+ appearance: none;
+ border-radius: 0.25rem;
+ transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
+ box-shadow: none !important;
+ margin-bottom: 10px !important;
+}
+
+form label {
+ font-weight: 400 !important;
+}
+
+.o-login-form a.btn.btn-secondary {
+ height: 40px;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 0.35rem 0.75rem;
+}
+
+.o-login-form a.btn.btn-secondary i.fa.fa-database {
+ margin-left: 5px;
+}
+
+/* Responsive Adjustments */
+@media (max-width: 576px) {
+ .card.o-database-list {
+ max-width: 100% !important;
+ }
+
+ .card.o-database-list .card-body {
+ width: 100%;
+ }
+
+ .o-login-form input {
+ font-size: 12px;
+ padding: 8px 15px;
+ }
+
+ .o-login-form .btn {
+ padding: 0.4rem 0.6rem;
+ font-size: 12px;
+ }
+}
\ No newline at end of file
diff --git a/code_backend_theme/static/src/scss/navigation_bar.scss b/code_backend_theme/static/src/scss/navigation_bar.scss
new file mode 100644
index 0000000..1f0bbba
--- /dev/null
+++ b/code_backend_theme/static/src/scss/navigation_bar.scss
@@ -0,0 +1,376 @@
+/* SCSS Variables (assumed to be defined in the project) */
+$primary_accent: #556ee6 !default;
+$secondary_accent: #334332 !default;
+$inverse_accent: #ffffff !default;
+$o-kanban-color-border-width: 8px;
+$selected_row: #ffffff !default;
+$bg_white: #ffffff !default;
+$f_color: #555b6d !default;
+$primary_hover: #485ec4 !default;
+
+/* Form Status Bar */
+.o-form-statusbar {
+ .o-statusbar-buttons {
+ .btn {
+ margin-right: 30px !important;
+ }
+ }
+}
+
+/* Control Panel Left */
+.o-control-panel-left {
+ .btn {
+ margin-right: 10px !important;
+ }
+}
+
+/* Calendar Buttons */
+.o-calendar-buttons > button > .fa {
+ color: #ffffff !important;
+}
+
+/* Main Navbar and Primary Buttons */
+.o-main-navbar, .btn-primary, .btn-primary:active, .o-searchview-facet-label {
+ background-color: $primary_accent !important;
+ color: $inverse_accent !important;
+}
+
+.o-search-panel-section-icon {
+ color: $primary_accent !important;
+}
+
+.btn-secondary {
+ border-radius: 0;
+ border: solid 1px $primary_accent !important;
+ color: $primary_accent !important;
+}
+
+/* List View Table */
+.o-list-view .o-list-table thead {
+ position: sticky;
+ top: 0;
+ z-index: 999;
+ background-color: #eeeeee !important;
+}
+
+.o-list-view .table-responsive .table {
+ width: max-content !important;
+ min-width: 100%;
+}
+
+.o-list-view .table-responsive .table thead tr:nth-child(1) th {
+ position: sticky;
+ top: 0;
+ z-index: 999;
+ background-color: #eeeeee !important;
+}
+
+.o-list-view .o-list-table tbody {
+ position: initial !important;
+}
+
+.o-list-view .table-responsive .table thead {
+ z-index: 1;
+}
+
+.o-optional-columns-dropdown-toggle {
+ z-index: 999;
+}
+
+/* Breadcrumb and Menu Items */
+.breadcrumb-item > a, .o-menu-item > a {
+ color: $primary_accent !important;
+}
+
+.fa-trash {
+ color: #f46a6a !important;
+}
+
+/* Navbar Hover States */
+.o-main-navbar > a:hover {
+ background-color: lighten($primary_accent, 10%) !important;
+}
+
+.o-main-navbar > .o-menu-sections > li > a:hover,
+.o-main-navbar > .o-menu-systray > li > a:hover,
+.o-main-navbar > .o-menu-sections > li.show > a,
+.o-main-navbar > .o-menu-systray > li.show > a {
+ background-color: lighten($primary_accent, 10%) !important;
+}
+
+.o-main-navbar > .o-menu-apps > li > a:hover,
+.o-main-navbar > .o-menu-apps > li > a:active {
+ background-color: lighten($primary_accent, 10%) !important;
+}
+
+.o-main-navbar > .o-menu-apps > .dropdown.show > .dropdown-menu.show {
+ max-height: 100vh !important;
+ height: 93vh !important;
+}
+
+/* Discuss Sidebar */
+.o-mail-discuss-sidebar {
+ background-color: #1c2833;
+}
+
+/* Dropdown Toggle */
+.dropdown-toggle::after {
+ background-color: transparent !important;
+}
+
+.o-external-button {
+ border: none !important;
+}
+
+.o-field-x2many-list-row-add > a {
+ color: $primary_accent !important;
+}
+
+.nav-item > a {
+ color: $primary_accent !important;
+}
+
+.o-main-navbar > .o-menu-apps > li > a > i {
+ color: $inverse_accent !important;
+ font-size: 16px !important;
+}
+
+.o-form-uri > span {
+ color: $primary_accent !important;
+}
+
+/* Input Fields */
+.o-required-modifier.o-input,
+.o-required-modifier .o-input,
+.o-required-modifier > .o-input-dropdown > .ui-autocomplete-input,
+.o-datepicker.o-field-date.o-field-widget.o-required-modifier > input {
+ background-color: $inverse_accent !important;
+ color: $primary_accent !important;
+ border-left: solid 3px #f46a6a !important;
+}
+
+.o-input {
+ border: solid 1px $primary_accent !important;
+ color: $primary_accent !important;
+}
+
+.o-no-caret > i, button[aria-pressed="true"] {
+ color: $inverse_accent !important;
+}
+
+.o-loading {
+ background-color: $primary_accent;
+}
+
+.fas {
+ color: $inverse_accent !important;
+}
+
+.dashboard-mainbar {
+ width: 100%;
+}
+
+.a-app-menu-title {
+ display: none;
+}
+
+.o-menu-apps > .dropdown.show > .dropdown-menu.show:hover .a-app-menu-title {
+ display: inline-block;
+ width: 200px;
+}
+
+.ui-state-active {
+ background-color: $primary_accent !important;
+ color: $inverse_accent !important;
+}
+
+.oe-search-bgnd {
+ background-color: lighten($primary_accent, 20%) !important;
+ color: $inverse_accent !important;
+}
+
+.oe-search-tab {
+ background-color: $primary_accent !important;
+ color: $inverse_accent !important;
+}
+
+.o-horizontal-separator {
+ color: $primary_accent !important;
+}
+
+.o-field-widget.o-field-image .o-form-image-controls {
+ background-color: $primary_accent !important;
+}
+
+.o-field-widget.o-field-image .o-form-image-controls > button {
+ color: $inverse_accent !important;
+}
+
+.dropdown-item.o-app.mt0:hover,
+.dropdown-item.o-app.mt0:hover > .a-app-menu-title {
+ background-color: $primary_accent !important;
+ color: $inverse_accent !important;
+}
+
+div.o-boolean-toggle.custom-control.custom-checkbox > input.custom-control-input:checked + label.custom-control-label::before {
+ background-color: $primary_accent !important;
+}
+
+.o-mail-systray-item .o-mail-systray-dropdown .o-filter-button.active {
+ color: $primary_accent;
+ text-decoration: none;
+}
+
+.o-mail-user-status.o-user-online {
+ color: #fff !important;
+}
+
+.o-form-view .o-form-statusbar > .o-statusbar-status > .o-arrow-button.btn-primary.disabled::after {
+ border-left-color: $primary_accent;
+}
+
+.btn-link {
+ font-weight: 400;
+ color: $primary_accent !important;
+ text-decoration: none;
+}
+
+.o-thread-window-header {
+ background-color: $primary_accent !important;
+}
+
+.o-thread-window-close, .o-thread-window-expand {
+ color: $inverse_accent !important;
+}
+
+.o-menu-sections, .o-menu-systray, .o-web-client > header {
+ background: $primary_accent !important;
+}
+
+.fa-building-o {
+ color: white !important;
+}
+
+/* Button Styling */
+.o-button-import, .oe-import-file {
+ background: #5aa29f !important;
+ color: white !important;
+ border: solid 2px #5aa29f !important;
+}
+
+.o-button-import:hover, .oe-import-file:hover,
+.o-button-import:active, .oe-import-file:active {
+ background: white !important;
+ color: #5aa29f !important;
+ border: solid 2px #5aa29f !important;
+}
+
+.o-form-button-save, .o-form-button-edit {
+ background: #7BA94F !important;
+ color: white !important;
+ border: solid 2px #7BA94F !important;
+}
+
+.o-form-button-save:hover, .o-form-button-edit:hover,
+.o-form-button-save:active, .o-form-button-edit:active {
+ background: white !important;
+ color: #7BA94F !important;
+ border: solid 2px #7BA94F !important;
+}
+
+.o-kanban-button-new, .o-list-button-add, .o-form-button-create {
+ background: #b9408d !important;
+ color: white !important;
+ border: solid 2px #b9408d !important;
+}
+
+.o-kanban-button-new:hover, .o-list-button-add:hover, .o-form-button-create:hover,
+.o-kanban-button-new:active, .o-list-button-add:active, .o-form-button-create:active {
+ background: white !important;
+ color: #b9408d !important;
+ border: solid 2px #b9408d !important;
+}
+
+.o-form-button-cancel, .o-import-cancel {
+ background: #cf4137 !important;
+ color: white !important;
+ border: solid 2px #cf4137 !important;
+}
+
+.o-form-button-cancel:hover, .o-import-cancel:hover,
+.o-form-button-cancel:active, .o-import-cancel:active {
+ background: white !important;
+ color: #cf4137 !important;
+ border: solid 2px #cf4137 !important;
+}
+
+.report-button {
+ border-radius: 0 !important;
+ border: solid 2px $primary_accent !important;
+ background: $primary_accent !important;
+}
+
+.report-button:hover, .report-button:active {
+ border-radius: 0 !important;
+ border: solid 2px $primary_accent !important;
+ color: $primary_accent !important;
+ background: $inverse_accent !important;
+}
+
+.btn-primary {
+ border-radius: 0 !important;
+}
+
+/* Navigation Tabs */
+.nav-tabs .nav-link.active, .nav-tabs .nav-item.show .nav-link {
+ border: none;
+ border-bottom: solid;
+ font-weight: bold;
+}
+
+.nav-link:hover, .nav-link:focus {
+ border: none;
+}
+
+/* Selected Rows */
+.o-data-row:has(.custom-control-input:checked) {
+ background: #E5E3F3 !important;
+}
+
+/* One2Many List View */
+.o-field-one2many .o-list-view .table-responsive {
+ max-height: 50vh;
+}
+
+/* Progress Bar */
+.o-progressbar .o-progress .o-progressbar-complete {
+ background-color: #3d9bbb;
+}
+
+/* Responsive Adjustments */
+@media (max-width: 992px) {
+ .o-main-navbar {
+ flex-wrap: wrap;
+ justify-content: flex-end;
+ height: auto;
+ }
+
+ .o-menu-systray {
+ margin-left: auto;
+ }
+}
+
+@media (max-width: 480px) {
+ .o-control-panel-left .btn {
+ margin-right: 5px !important;
+ }
+
+ .o-form-statusbar {
+ flex-wrap: wrap;
+ }
+
+ .o-main-navbar > .o-menu-apps > .dropdown.show > .dropdown-menu.show {
+ height: auto !important;
+ max-height: 80vh !important;
+ }
+}
\ No newline at end of file
diff --git a/code_backend_theme/static/src/scss/sidebar.scss b/code_backend_theme/static/src/scss/sidebar.scss
new file mode 100644
index 0000000..57dfc94
--- /dev/null
+++ b/code_backend_theme/static/src/scss/sidebar.scss
@@ -0,0 +1,139 @@
+/* Sidebar Panel */
+#sidebar-panel {
+ height: 100%;
+ position: fixed;
+ top: 0;
+ background-color: #2a3042;
+ display: none;
+ width: 200px;
+ overflow-y: auto;
+ scrollbar-width: none; /* Hide scrollbar for Firefox */
+ z-index: 999;
+}
+
+#sidebar-panel::-webkit-scrollbar {
+ display: none; /* Hide scrollbar for Chrome, Safari, and Opera */
+}
+
+.sidebar-panel .sidebar {
+ padding: 0;
+ white-space: nowrap;
+ padding-bottom: 20px;
+ padding-top: 5px;
+}
+
+.sidebar-panel .sidebar-close {
+ text-align: end;
+ display: none;
+ position: sticky;
+ height: 35px;
+ padding-top: 5px;
+ top: 0;
+ background: #2a3042;
+ z-index: 1;
+}
+
+.sidebar-panel .sidebar-close a#closeSidebar {
+ font-size: 18px;
+ margin-right: 10px;
+ color: #ffffff;
+ opacity: 0.3;
+}
+
+.sidebar-panel .sidebar-close a#closeSidebar img {
+ width: 15px;
+}
+
+.sidebar-panel .sidebar .sidebar-logo {
+ padding-top: 20px;
+ text-align: center;
+ padding-bottom: 20px;
+}
+
+.sidebar-panel .sidebar .sidebar-logo img {
+ max-width: 150px;
+}
+
+.sidebar-panel .sidebar .sidebar-head {
+ padding-top: 20px;
+ padding-left: 15px;
+ color: #6a7187;
+ font-size: 14px;
+}
+
+.sidebar-panel .sidebar .sidebar-menu {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+}
+
+.sidebar-panel .sidebar .sidebar-menu li {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ display: block;
+}
+
+.sidebar-panel .sidebar .sidebar-menu li a {
+ margin: 0;
+ border: 0;
+ display: block;
+ cursor: pointer;
+ overflow: hidden;
+ padding: 8px 10px 8px 25px;
+ color: #ffffff;
+ font-size: 13px;
+ transition: all 0.3s;
+}
+
+.sidebar-panel .sidebar .sidebar-menu li:hover a {
+ background: #1e2230;
+ color: #fff;
+}
+
+.sidebar-panel .nav-link {
+ opacity: 0.5;
+ transition: all 0.3s;
+}
+
+.sidebar-panel .sidebar a.nav-link.active {
+ color: #fff !important;
+ opacity: 1;
+}
+
+.sidebar-panel .sidebar .sidebar-menu li a .sidebar-img {
+ width: 20px;
+ margin-right: 8px;
+}
+
+/* Responsive Adjustments for Odoo 18 */
+@media (max-width: 992px) {
+ #sidebar-panel {
+ width: 100%;
+ z-index: 1000;
+ display: none; /* Hidden by default, toggled via JS in Odoo 18 */
+ }
+
+ .sidebar-panel .sidebar-close {
+ display: block;
+ }
+
+ .o-web-client.sidebar-open #sidebar-panel {
+ display: block; /* Show sidebar when toggled */
+ }
+}
+
+@media (max-width: 480px) {
+ #sidebar-panel {
+ width: 100%;
+ }
+
+ .sidebar-panel .sidebar .sidebar-logo img {
+ max-width: 120px;
+ }
+
+ .sidebar-panel .sidebar .sidebar-menu li a {
+ padding: 8px 10px 8px 15px;
+ font-size: 12px;
+ }
+}
\ No newline at end of file
diff --git a/code_backend_theme/static/src/scss/theme.scss b/code_backend_theme/static/src/scss/theme.scss
new file mode 100644
index 0000000..119fbd1
--- /dev/null
+++ b/code_backend_theme/static/src/scss/theme.scss
@@ -0,0 +1,792 @@
+/* Defining SCSS variables (assumed to be available in the project) */
+$primary_accent: #556ee6 !default;
+$secondary_accent: #334332 !default;
+$inverse_accent: #ffffff !default;
+$o-kanban-color-border-width: 8px;
+$selected_row: #ffffff !default;
+$bg_white: #ffffff !default;
+$f_color: #555b6d !default;
+$primary_hover: #485ec4 !default;
+
+/* General Body Styling */
+body {
+ font-family: 'Poppins', sans-serif !important;
+ background-color: #f8f8fb;
+}
+
+a {
+ color: $primary_accent;
+}
+
+a:hover {
+ color: $primary_hover;
+}
+
+a.btn {
+ height: auto !important;
+}
+
+/* Top Bar (Updated for Odoo 18) */
+.o-main-navbar, .o-searchview-facet-label {
+ background-color: transparent !important;
+ color: $f_color !important;
+ border: none !important;
+}
+
+.o-menu-sections, .o-menu-systray, .o-web-client > header {
+ background: $bg_white !important;
+}
+
+.o-user-menu-name {
+ color: $f_color !important;
+}
+
+.o-main-navbar > .o-menu-apps > li > a > i {
+ color: $f_color !important;
+ font-size: 16px !important;
+}
+
+.o-main-navbar {
+ height: 65px;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ border-bottom: none !important;
+ box-shadow: 0 0.75rem 1.5rem rgba(18, 38, 63, 0.03) !important;
+ background-color: #fff !important;
+}
+
+.top-heading {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+.top-heading ul {
+ margin-bottom: 0 !important;
+}
+
+.top-heading > a {
+ margin-left: 10px;
+ font-size: 20px;
+}
+
+.top-heading li {
+ list-style: none;
+}
+
+.o-no-caret > i, button[aria-pressed="true"] {
+ color: $f_color !important;
+}
+
+.o-main-navbar > ul > li > a, .o-main-navbar > ul > li > label {
+ height: 46px;
+ padding: 0 5px;
+ color: $f_color !important;
+ line-height: 46px;
+}
+
+.o-main-navbar > .o-menu-sections > li > a:hover,
+.o-main-navbar > .o-menu-systray > li > a:hover,
+.o-main-navbar > .o-menu-sections > li.show > a,
+.o-main-navbar > .o-menu-systray > li.show > a {
+ background-color: $bg_white !important;
+}
+
+.topbar-icon .fa {
+ color: #555b6d !important;
+ font-size: 20px !important;
+}
+
+.o-main-navbar .o-user-menu .o-user-avatar {
+ height: 35px;
+ width: 35px;
+}
+
+.o-messaging-menu-counter {
+ background-color: #556ee6;
+ color: #fff !important;
+}
+
+.o-mail-systray-item .o-notification-counter {
+ background: #556ee6 !important;
+}
+
+.o-control-panel {
+ background: #f8f8fb !important;
+ border: none !important;
+ margin: 15px 15px 0 15px;
+ background-color: #ffffff !important;
+ box-shadow: 0 0.75rem 1.5rem rgba(18, 38, 63, 0.03) !important;
+ border-radius: 5px;
+}
+
+.o-searchview {
+ border: 1px solid #ddd;
+ height: 38px;
+ padding-left: 12px;
+ padding-right: 20px;
+ box-shadow: none;
+ border-radius: 5px;
+ padding-top: 6px;
+}
+
+.o-searchview .o-searchview-icon {
+ position: absolute;
+ top: 11px;
+ right: 8px;
+}
+
+.o-searchview .o-searchview-facet {
+ border: 1px solid #ddd;
+ background: #f8f8fb;
+ border-radius: 10px;
+ padding: 0 4px;
+}
+
+.o-control-panel-bottom-right span.o-dropdown-title {
+ color: #555b6d;
+}
+
+.o-control-panel-bottom-left .o-form-button-cancel {
+ margin-right: 5px !important;
+ padding: 6px 8px !important;
+ color: #fff !important;
+ background-color: #f46a6a !important;
+ border-color: #f46a6a !important;
+}
+
+.o-control-panel-bottom-left .o-form-button-cancel:hover {
+ background-color: #cf5a5a !important;
+ border-color: #c35555 !important;
+}
+
+.o-form-view, .o-widget-discuss {
+ background: #f8f8fb;
+}
+
+.o-form-view .o-form-statusbar > .o-statusbar-buttons .btn {
+ margin-right: 15px !important;
+}
+
+.o-form-view .o-form-statusbar > .o-statusbar-status > .o-arrow-button:not(:first-child)::before,
+.o-form-view .o-form-statusbar > .o-statusbar-status > .o-arrow-button:not(:first-child)::after {
+ border-top: 21px solid transparent !important;
+ border-bottom: 17px solid transparent !important;
+}
+
+.o-form-view .o-form-statusbar > .o-statusbar-status > .o-arrow-button:not(:first-child)::before {
+ right: -11px;
+ border-left-color: $primary_accent;
+}
+
+/* Buttons */
+.btn {
+ display: inline-block;
+ font-weight: 400 !important;
+ line-height: 1.5 !important;
+ color: #495057;
+ text-align: center;
+ vertical-align: middle;
+ cursor: pointer;
+ user-select: none;
+ background-color: transparent;
+ border: 1px solid transparent;
+ padding: 6px 15px !important;
+ border-radius: 4px !important;
+ transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
+ height: 40px !important;
+ margin-bottom: 2px;
+}
+
+.btn-primary {
+ color: #fff !important;
+ background-color: $primary_accent !important;
+ border-color: $primary_accent !important;
+}
+
+.btn-primary:hover {
+ color: #fff !important;
+ background-color: $primary_hover !important;
+ border-color: #4458b8 !important;
+}
+
+.btn-primary:active {
+ color: #fff !important;
+ background-color: #4458b8 !important;
+ border-color: #4053ad !important;
+}
+
+.btn-check:focus + .btn-primary, .btn-primary:focus {
+ color: #fff;
+ background-color: #485ec4 !important;
+ border-color: #4458b8 !important;
+ box-shadow: 0 0 0 0.15rem rgba(111, 132, 234, 0.5) !important;
+}
+
+.btn-primary i, .btn-primary span {
+ color: #fff !important;
+}
+
+.btn-secondary {
+ color: #fff !important;
+ background-color: #74788d !important;
+ border-color: #74788d !important;
+}
+
+.btn-secondary:hover {
+ color: #fff !important;
+ background-color: #636678 !important;
+ border-color: #5d6071 !important;
+}
+
+.btn-secondary:active {
+ color: #fff;
+ background-color: #5d6071 !important;
+ border-color: #575a6a !important;
+}
+
+.btn-check:focus + .btn-secondary, .btn-secondary:focus {
+ color: #fff;
+ background-color: #636678 !important;
+ border-color: #5d6071 !important;
+ box-shadow: 0 0 0 0.15rem rgba(137, 140, 158, 0.5) !important;
+}
+
+.btn-secondary i, .btn-secondary span {
+ color: #fff !important;
+}
+
+.btn-info {
+ color: #fff !important;
+ background-color: #50a5f1 !important;
+ border-color: #50a5f1 !important;
+}
+
+.btn-info:hover {
+ color: #fff !important;
+ background-color: #448ccd !important;
+ border-color: #4084c1 !important;
+}
+
+button[name="action_cancel"],
+button[name="button_cancel"],
+button[special="cancel"] {
+ color: #fff !important;
+ background-color: #f46a6a !important;
+ border-color: #f46a6a !important;
+}
+
+button[name="action_cancel"]:hover,
+button[name="button_cancel"]:hover,
+button[special="cancel"]:hover {
+ background-color: #cf5a5a !important;
+ border-color: #c35555 !important;
+}
+
+button[name="action_cancel"]:active,
+button[name="button_cancel"]:active,
+button[special="cancel"]:active {
+ color: #fff !important;
+ background-color: #c35555 !important;
+ border-color: #b75050 !important;
+}
+
+button[name="action_cancel"]:focus,
+button[name="button_cancel"]:focus,
+button[special="cancel"]:focus {
+ color: #fff !important;
+ background-color: #cf5a5a !important;
+ border-color: #c35555 !important;
+ box-shadow: 0 0 0 0.15rem rgba(246, 128, 128, 0.5) !important;
+}
+
+button[name="update_module"] {
+ margin-right: 2px;
+}
+
+.btn-warning,
+button[name="action_uninstall"] {
+ color: #fff !important;
+ background-color: #f1b44c !important;
+ border-color: #f1b44c !important;
+}
+
+.btn-warning:hover,
+button[name="action_uninstall"]:hover {
+ color: #fff !important;
+ background-color: #cd9941 !important;
+ border-color: #c1903d !important;
+}
+
+.btn-warning:active,
+button[name="action_uninstall"]:active {
+ color: #fff !important;
+ background-color: #c1903d !important;
+ border-color: #b58739 !important;
+}
+
+.btn-warning:focus,
+button[name="action_uninstall"]:focus {
+ color: #fff !important;
+ background-color: #cd9941 !important;
+ border-color: #c1903d !important;
+ box-shadow: 0 0 0 0.15rem rgba(243, 191, 103, 0.5) !important;
+}
+
+.o-statusbar-status .o-arrow-button.btn-secondary {
+ border: solid 1px #556ee6 !important;
+ color: #556ee6 !important;
+ background-color: #fff !important;
+}
+
+.o-statusbar-status .o-arrow-button.btn-secondary:hover::after {
+ border-color: #fff !important;
+}
+
+.o-statusbar-status .o-arrow-button.btn-primary {
+ border: solid 1px #556ee6 !important;
+ color: #fff !important;
+}
+
+.o-control-panel-bottom-right .btn-secondary {
+ background: #fff;
+ border-color: #dddddd !important;
+ margin-right: 5px !important;
+ padding: 6px 8px !important;
+}
+
+.o-control-panel-bottom-left .o-form-button-create {
+ color: #fff !important;
+ background-color: #74788d !important;
+ border-color: #74788d !important;
+ padding: 5px 15px !important;
+}
+
+.o-web-settings-invite {
+ margin-left: 7px;
+ position: relative;
+ top: -1px;
+}
+
+.o-form-view .oe-button-box .btn.oe-stat-button {
+ height: 44px !important;
+ opacity: 1 !important;
+ border-radius: 0 !important;
+}
+
+.oe-module-action .btn {
+ height: auto !important;
+}
+
+.o-control-panel-buttons a.btn {
+ display: flex !important;
+ align-items: center;
+}
+
+button.fa.fa-external-link.btn.btn-secondary.o-external-button {
+ padding: 2px !important;
+ color: #74788d !important;
+ background: none !important;
+}
+
+.o-statusbar-status.o-field-widget.o-readonly-modifier .btn {
+ margin-right: 0 !important;
+}
+
+.btn-group .btn {
+ margin-right: 3px;
+}
+
+.o-composer-action-button.o-last.o-has-current-partner-avatar.o-composer-is-compact {
+ height: 48px !important;
+ border-bottom-left-radius: 0 !important;
+ border-top-left-radius: 0 !important;
+}
+
+.oe-right .btn {
+ margin-left: 2px;
+}
+
+/* Tables */
+.table-sm th, .table-sm td {
+ padding: 0.5rem;
+}
+
+tr.o-data-row {
+ font-size: 15px;
+}
+
+.o-list-view .table-responsive .table thead tr:nth-child(1) th {
+ position: sticky;
+ top: 0;
+ z-index: 999;
+ background-color: #ffffff !important;
+}
+
+th.o-list-record-selector {
+ color: #495057 !important;
+ border-color: #eff2f7 !important;
+ background-color: #f8f9fa !important;
+}
+
+.table > :not(caption) > * > * {
+ padding: 1rem;
+ background-color: var(--bs-table-bg);
+ border-bottom-width: 1px;
+ box-shadow: inset 0 0 0 9999px var(--bs-table-accent-bg);
+}
+
+.o-list-view .o-list-table thead > tr > th:not(.o-list-record-selector).o-list-number-th {
+ text-align: left !important;
+}
+
+.o-list-view .o-list-table thead > tr > th:not(.o-list-record-selector) {
+ border-left: none !important;
+}
+
+.table thead th {
+ vertical-align: bottom;
+ border-bottom: none;
+}
+
+.table th {
+ border-top: 1px solid #fff !important;
+}
+
+.o-list-view .o-list-table tfoot {
+ background-color: #fff !important;
+}
+
+.o-list-view .table-responsive .o-list-table tfoot tr:nth-child(1) td {
+ background-color: #fff !important;
+}
+
+.o-list-view .o-list-table tr:focus-within,
+.o-list-view .o-list-table.table-striped tr:focus-within {
+ background-color: #fff !important;
+}
+
+/* Checkbox */
+.custom-checkbox label {
+ position: relative;
+ cursor: pointer;
+}
+
+.custom-checkbox label::before {
+ content: '';
+ appearance: none;
+ background-color: transparent;
+ border: 1px solid #0079bf;
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05), inset 0 -15px 10px -12px rgba(0, 0, 0, 0.05);
+ padding: 10px;
+ display: inline-block;
+ position: relative;
+ vertical-align: middle;
+ cursor: pointer;
+ margin-right: 5px;
+ margin-top: 0;
+}
+
+.custom-checkbox input:checked + label::after {
+ content: '';
+ display: block;
+ position: absolute;
+ top: 1px;
+ left: 9px;
+ width: 6px;
+ height: 14px;
+ border: solid #fff;
+ border-width: 0 2px 2px 0;
+ transform: rotate(45deg);
+}
+
+.custom-control-label::before {
+ position: absolute;
+ top: 0 !important;
+ left: 1px !important;
+ display: block;
+ width: 1rem;
+ height: 1rem;
+ pointer-events: none;
+ content: "";
+ background-color: #fff;
+ border: 1px solid rgba(0, 0, 0, 0.25) !important;
+ box-shadow: none !important;
+ border-radius: 5px !important;
+ margin-top: -5px;
+}
+
+.custom-checkbox {
+ padding-left: 0 !important;
+}
+
+.custom-checkbox .custom-control-input:disabled:checked ~ .custom-control-label::before {
+ background-color: $primary_accent;
+}
+
+.dropdown-item .custom-checkbox input:checked + label::after {
+ content: '';
+ display: block;
+ position: absolute;
+ top: 1px;
+ left: 19px;
+ width: 6px;
+ height: 14px;
+ border: solid #fff;
+ border-width: 0 2px 2px 0;
+ transform: rotate(45deg);
+}
+
+.custom-control-input:checked ~ .custom-control-label::before {
+ color: #fff;
+ background-color: #556ee6;
+ border-color: #556ee6;
+}
+
+.custom-control.custom-checkbox .custom-control-input:not(:checked):not(:indeterminate) ~ .custom-control-label::before {
+ background: none;
+ outline: none !important;
+}
+
+.o-list-selection-box {
+ display: inline-block;
+ padding: 0.375rem 0.75rem;
+ vertical-align: middle;
+ border: 1px solid rgba(85, 110, 230, 0.25) !important;
+ background-color: rgba(85, 110, 230, 0.25) !important;
+ color: $primary_accent !important;
+ border-radius: 5px;
+}
+
+.o-radio-input + .custom-control-label::before {
+ position: absolute !important;
+ top: 8.5px !important;
+ left: -1.5rem !important;
+ display: block !important;
+ width: 1rem !important;
+ height: 1rem !important;
+ pointer-events: none !important;
+ content: "" !important;
+ background-color: #fff !important;
+ border: #adb5bd solid 1px !important;
+}
+
+.custom-radio .custom-control-input:checked ~ .custom-control-label::after {
+ background: $primary_accent !important;
+ border-radius: 30px;
+}
+
+/* Form Sheet */
+.o-form-view .o-form-sheet-bg {
+ border-bottom: none;
+ background: #fff !important;
+ box-shadow: none !important;
+ border-radius: 5px;
+ padding: 10px;
+}
+
+.o-form-view .o-form-sheet-bg > .o-form-sheet {
+ min-width: 650px;
+ max-width: initial;
+ min-height: 330px;
+ border: 1px solid #c8c8d3;
+ box-shadow: none !important;
+ background: #fff;
+ margin: 4.8px auto;
+ padding: 24px 16px;
+ border-radius: 5px;
+}
+
+.o-form-view .o-form-statusbar {
+ position: relative;
+ display: flex;
+ justify-content: space-between;
+ padding-left: 5px;
+ border-bottom: none !important;
+ background-color: #fff;
+ border-radius: 5px;
+}
+
+.o-required-modifier > .o-input-dropdown > .ui-autocomplete-input {
+ border-left: solid 3px #f46a6a !important;
+}
+
+/* Discuss */
+.o-discuss {
+ padding: 15px !important;
+ background: #f5f5f9 !important;
+}
+
+.o-discuss .o-discuss-sidebar {
+ background-color: #fff !important;
+ color: #dee2e6 !important;
+ border-radius: 5px;
+ margin-right: 10px !important;
+ box-shadow: 0 0.75rem 1.5rem rgba(18, 38, 63, 0.03) !important;
+}
+
+.o-discuss-sidebar-item.o-active {
+ color: #f46a6a !important;
+ font-weight: 500 !important;
+}
+
+.o-discuss-sidebar-item:hover {
+ background: none !important;
+}
+
+.o-discuss-sidebar-item {
+ cursor: pointer !important;
+ color: #74788d !important;
+ line-height: 24px !important;
+ padding: 10px 5px !important;
+}
+
+.o-discuss-sidebar-item-active-indicator.o-item-active {
+ background: none !important;
+}
+
+.o-discuss-sidebar-item.o-active .fa {
+ color: #f46a6a !important;
+}
+
+.o-widget-discuss .o-discuss-content {
+ border-top: none !important;
+ background-color: #fff !important;
+ border-radius: 5px;
+ box-shadow: 0 0.75rem 1.5rem rgba(18, 38, 63, 0.03) !important;
+}
+
+.o-discuss-sidebar-item-counter {
+ background-color: #f46a6a !important;
+ color: #fff !important;
+}
+
+.o-thread-icon-online {
+ color: #34c38f;
+}
+
+.o-message-pretty-body table th {
+ color: $primary_accent !important;
+}
+
+.o-message-pretty-body table thead tr td {
+ background-color: $primary_hover !important;
+}
+
+/* Responsive */
+@media (max-width: 992px) {
+ .o-action-manager.sidebar-margin {
+ margin: 0 !important;
+ }
+ .top-heading.sidebar-margin {
+ margin: 0 !important;
+ }
+ .sidebar-panel .sidebar {
+ position: relative;
+ padding-top: 0 !important;
+ }
+ .sidebar-panel .sidebar-close {
+ display: block !important;
+ }
+}
+
+@media (max-width: 480px) {
+ ul.o-menu-apps {
+ padding-left: 25px;
+ }
+ .o-control-panel {
+ margin: 15px 10px 0 10px;
+ }
+ .o-control-panel > div {
+ flex-wrap: wrap;
+ }
+ .o-control-panel-top-left, .o-control-panel-top-right,
+ .o-control-panel-bottom-left, .o-control-panel-bottom-right {
+ width: 100%;
+ }
+ .o-widget-discuss .o-discuss.o-mobile:not(.o-adding-item) {
+ border: none !important;
+ }
+ html .o-web-client > .o-action-manager {
+ overflow: auto !important;
+ }
+ ul.o-menu-systray.topbar-icon li:nth-child(1) {
+ margin-left: 20px;
+ }
+ .o-main-navbar .o-user-menu {
+ margin-left: 20px;
+ }
+ .sidebar-panel .sidebar .sidebar-logo img {
+ max-width: 112px;
+ }
+ .sidebar-panel .sidebar .sidebar-logo {
+ padding-top: 20px;
+ text-align: center;
+ padding-bottom: 5px;
+ }
+ li.o-switch-company-menu.show .dropdown-menu.dropdown-menu-right.show {
+ right: auto !important;
+ left: 0;
+ }
+ ul.o-menu-systray.topbar-icon .dropdown-menu.show {
+ left: 0 !important;
+ right: auto !important;
+ }
+ ul.o-menu-systray.topbar-icon {
+ margin-left: 0;
+ }
+ .o-messaging-menu-dropdown-menu.o-mobile {
+ top: 70px;
+ }
+ .o-control-panel .o-control-panel-bottom-right {
+ flex-wrap: wrap;
+ }
+ .o-form-view .o-form-statusbar {
+ flex-wrap: wrap;
+ }
+ .btn {
+ padding: 2px 10px !important;
+ height: 35px !important;
+ }
+ .o-form-view .o-form-statusbar > .o-statusbar-status > .o-arrow-button:not(:first-child)::before,
+ .o-form-view .o-form-statusbar > .o-statusbar-status > .o-arrow-button:not(:first-child)::after {
+ border-top: 17px solid transparent !important;
+ border-bottom: 16px solid transparent !important;
+ }
+ .o-statusbar-status.o-field-widget.o-readonly-modifier {
+ width: 100%;
+ justify-content: flex-end;
+ margin-top: 5px;
+ }
+ .o-form-view .o-form-statusbar > .o-statusbar-buttons > .btn {
+ margin: 1px 0 4px 0;
+ }
+ .o-form-statusbar .o-statusbar-buttons .btn {
+ margin-right: 5px !important;
+ }
+ .o-control-panel .o-control-panel-bottom-left > .o-control-panel-action-menus .o-dropdown-toggler-btn {
+ margin-right: 3px;
+ }
+ .o-form-view .o-form-sheet-bg > .o-form-sheet {
+ min-width: auto;
+ }
+ .nav-tabs .nav-link {
+ padding: 8px;
+ }
+ .modal.o-technical-modal.o-modal-full .modal-dialog .modal-content .modal-header {
+ background: $primary_accent;
+ }
+ .o-form-view .o-group .o-group-col-6 {
+ width: 100%;
+ }
+ .o-kanban-view.o-kanban-ungrouped .o-kanban-record {
+ flex-wrap: wrap;
+ }
+ .o-kanban-view .o-kanban-record.o-kanban-record-has-image-fill .o-kanban-image-fill-left {
+ border-radius: 5px;
+ }
+ .o-field-widget.o-field-image .o-form-image-controls > .fa.o-select-file-button {
+ background: #74788d;
+ }
+}
\ No newline at end of file
diff --git a/code_backend_theme/static/src/scss/theme_accent.scss b/code_backend_theme/static/src/scss/theme_accent.scss
new file mode 100644
index 0000000..0ed3784
--- /dev/null
+++ b/code_backend_theme/static/src/scss/theme_accent.scss
@@ -0,0 +1,79 @@
+/* ================================
+ Root CSS Variables (v18 standard)
+ ================================ */
+:root {
+ /* Primary color scheme */
+ --o-color-primary: #556ee6;
+ --o-color-secondary: #334332;
+ --o-color-inverse: #ffffff;
+
+ /* Kanban specific */
+ --o-kanban-border-width: 8px;
+ --o-kanban-selected-background: #f5f7fa; /* subtle gray instead of pure white */
+
+ /* Background and text */
+ --o-color-background: #ffffff;
+ --o-color-text-primary: #555b6d;
+ --o-color-primary-hover: #485ec4;
+
+ /* Aliases for compatibility */
+ --o-main-color-muted: var(--o-color-text-primary);
+ --o-brand-primary: var(--o-color-primary);
+ --o-brand-secondary: var(--o-color-secondary);
+}
+
+/* ================================
+ SCSS Variable Mappings (optional)
+ ================================ */
+$o-color-primary: var(--o-color-primary) !default;
+$o-color-secondary: var(--o-color-secondary) !default;
+$o-color-inverse: var(--o-color-inverse) !default;
+$o-kanban-border-width: var(--o-kanban-border-width) !default;
+$o-selected-row-bg: var(--o-kanban-selected-background) !default;
+$o-background: var(--o-color-background) !default;
+$o-text-color-primary: var(--o-color-text-primary) !default;
+$o-primary-hover: var(--o-color-primary-hover) !default;
+
+/* ================================
+ Component Styling
+ ================================ */
+.o-kanban-card {
+ border-left: var(--o-kanban-border-width) solid var(--o-color-primary);
+ background-color: var(--o-color-background);
+ color: var(--o-color-text-primary);
+
+ &:hover {
+ background-color: var(--o-color-primary-hover);
+ color: var(--o-color-inverse);
+ }
+
+ &.selected {
+ background-color: var(--o-kanban-selected-background);
+ border-left: var(--o-kanban-border-width) solid var(--o-color-secondary);
+ box-shadow: 0 0 6px rgba(0,0,0,0.1);
+ }
+}
+
+.o-form-view {
+ background-color: var(--o-color-background);
+ color: var(--o-color-text-primary);
+}
+
+.btn-primary-custom {
+ background-color: var(--o-color-primary);
+ border-color: var(--o-color-primary);
+ color: var(--o-color-inverse);
+
+ &:hover {
+ background-color: var(--o-color-primary-hover);
+ border-color: var(--o-color-primary-hover);
+ }
+
+ &:disabled {
+ background-color: var(--o-main-color-muted);
+ border-color: var(--o-main-color-muted);
+ color: var(--o-color-inverse);
+ opacity: 0.6;
+ cursor: not-allowed;
+ }
+}
diff --git a/code_backend_theme/static/src/xml/sidebar.xml b/code_backend_theme/static/src/xml/sidebar.xml
new file mode 100644
index 0000000..f1ea949
--- /dev/null
+++ b/code_backend_theme/static/src/xml/sidebar.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
diff --git a/code_backend_theme/static/src/xml/styles.xml b/code_backend_theme/static/src/xml/styles.xml
new file mode 100644
index 0000000..52c2b27
--- /dev/null
+++ b/code_backend_theme/static/src/xml/styles.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+ d-flex align-items-center
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ o_search_panel_counter ms-2 small
+
+
+
+
diff --git a/code_backend_theme/static/src/xml/top_bar.xml b/code_backend_theme/static/src/xml/top_bar.xml
new file mode 100644
index 0000000..dc12846
--- /dev/null
+++ b/code_backend_theme/static/src/xml/top_bar.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
diff --git a/code_backend_theme/views/icons.xml b/code_backend_theme/views/icons.xml
new file mode 100644
index 0000000..62d0265
--- /dev/null
+++ b/code_backend_theme/views/icons.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/code_backend_theme/views/layout.xml b/code_backend_theme/views/layout.xml
new file mode 100644
index 0000000..2592f50
--- /dev/null
+++ b/code_backend_theme/views/layout.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/exp_base_document_layout_fonts/__init__.py b/exp_base_document_layout_fonts/__init__.py
new file mode 100644
index 0000000..f5ba686
--- /dev/null
+++ b/exp_base_document_layout_fonts/__init__.py
@@ -0,0 +1,2 @@
+# -*- coding: utf-8 -*-
+from . import models
\ No newline at end of file
diff --git a/exp_base_document_layout_fonts/__manifest__.py b/exp_base_document_layout_fonts/__manifest__.py
new file mode 100644
index 0000000..44aadae
--- /dev/null
+++ b/exp_base_document_layout_fonts/__manifest__.py
@@ -0,0 +1,24 @@
+# -*- coding: utf-8 -*-
+{
+ 'name': "Custom Document Layout Fonts",
+ 'version': '18.0.1.0.0',
+ 'category': 'Customizations',
+ 'summary': "Add custom fonts to the Base Document Layout in Odoo",
+ 'description': """
+This module adds custom fonts to the base.document.layout model, allowing users to select from new fonts
+such as Poppins, Roboto, and others for document templates.
+ """,
+ 'author': "AHIDev",
+ 'website': "http://www.exp-sa.com",
+ 'depends': ['base', 'web'],
+ 'data': [
+ #'views/webclient.xml',
+ ],
+ 'assets': {
+ 'web.assets_backend': [
+ 'exp_base_document_layout_fonts/static/src/scss/fonts.scss',
+ ],
+ },
+ 'installable': True,
+ 'application': False,
+}
diff --git a/exp_base_document_layout_fonts/models/__init__.py b/exp_base_document_layout_fonts/models/__init__.py
new file mode 100644
index 0000000..b4deb51
--- /dev/null
+++ b/exp_base_document_layout_fonts/models/__init__.py
@@ -0,0 +1 @@
+from . import document_layout
\ No newline at end of file
diff --git a/exp_base_document_layout_fonts/models/document_layout.py b/exp_base_document_layout_fonts/models/document_layout.py
new file mode 100644
index 0000000..4052715
--- /dev/null
+++ b/exp_base_document_layout_fonts/models/document_layout.py
@@ -0,0 +1,7 @@
+from odoo import models, fields
+
+class ResCompany(models.Model):
+ _inherit = 'res.company'
+
+ # Modify the selection field to include the new font option
+ font = fields.Selection(selection_add=[('DroidNaskh','DroidNaskh'),('DroidKufi', 'DroidKufi'),('Bukra','Bukra')])
\ No newline at end of file
diff --git a/exp_base_document_layout_fonts/static/description/icon.png b/exp_base_document_layout_fonts/static/description/icon.png
new file mode 100644
index 0000000..a37b596
Binary files /dev/null and b/exp_base_document_layout_fonts/static/description/icon.png differ
diff --git a/exp_base_document_layout_fonts/static/description/index.html b/exp_base_document_layout_fonts/static/description/index.html
new file mode 100644
index 0000000..895109b
--- /dev/null
+++ b/exp_base_document_layout_fonts/static/description/index.html
@@ -0,0 +1,83 @@
+
+
+
+ ONE OF ODEX MODULES
+
+ ODEX system is over than 200+ modules developed by love of Expert Company, based on ODOO system
+
+ .to effectively suite's Saudi and Arabic market needs.It is the first Arabic open source ERP and all-in-one
+ solution
+
+
+
+
+
+
+
diff --git a/exp_base_document_layout_fonts/static/description/internet.png b/exp_base_document_layout_fonts/static/description/internet.png
new file mode 100644
index 0000000..a89809b
Binary files /dev/null and b/exp_base_document_layout_fonts/static/description/internet.png differ
diff --git a/exp_base_document_layout_fonts/static/description/linkedin.png b/exp_base_document_layout_fonts/static/description/linkedin.png
new file mode 100644
index 0000000..a0fe09c
Binary files /dev/null and b/exp_base_document_layout_fonts/static/description/linkedin.png differ
diff --git a/exp_base_document_layout_fonts/static/description/mail.png b/exp_base_document_layout_fonts/static/description/mail.png
new file mode 100644
index 0000000..bc5a4de
Binary files /dev/null and b/exp_base_document_layout_fonts/static/description/mail.png differ
diff --git a/exp_base_document_layout_fonts/static/description/odex.png b/exp_base_document_layout_fonts/static/description/odex.png
new file mode 100644
index 0000000..de82c0e
Binary files /dev/null and b/exp_base_document_layout_fonts/static/description/odex.png differ
diff --git a/exp_base_document_layout_fonts/static/description/smiling_face.svg b/exp_base_document_layout_fonts/static/description/smiling_face.svg
new file mode 100644
index 0000000..250900e
--- /dev/null
+++ b/exp_base_document_layout_fonts/static/description/smiling_face.svg
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/exp_base_document_layout_fonts/static/description/twitter.png b/exp_base_document_layout_fonts/static/description/twitter.png
new file mode 100644
index 0000000..983f325
Binary files /dev/null and b/exp_base_document_layout_fonts/static/description/twitter.png differ
diff --git a/exp_base_document_layout_fonts/static/src/fonts/DroidKufi-Bold.eot b/exp_base_document_layout_fonts/static/src/fonts/DroidKufi-Bold.eot
new file mode 100644
index 0000000..c98ced3
Binary files /dev/null and b/exp_base_document_layout_fonts/static/src/fonts/DroidKufi-Bold.eot differ
diff --git a/exp_base_document_layout_fonts/static/src/fonts/DroidKufi-Bold.ttf b/exp_base_document_layout_fonts/static/src/fonts/DroidKufi-Bold.ttf
new file mode 100644
index 0000000..650919e
Binary files /dev/null and b/exp_base_document_layout_fonts/static/src/fonts/DroidKufi-Bold.ttf differ
diff --git a/exp_base_document_layout_fonts/static/src/fonts/DroidKufi-Bold.woff b/exp_base_document_layout_fonts/static/src/fonts/DroidKufi-Bold.woff
new file mode 100644
index 0000000..565c003
Binary files /dev/null and b/exp_base_document_layout_fonts/static/src/fonts/DroidKufi-Bold.woff differ
diff --git a/exp_base_document_layout_fonts/static/src/fonts/DroidKufi-Bold.woff2 b/exp_base_document_layout_fonts/static/src/fonts/DroidKufi-Bold.woff2
new file mode 100644
index 0000000..27f95d0
Binary files /dev/null and b/exp_base_document_layout_fonts/static/src/fonts/DroidKufi-Bold.woff2 differ
diff --git a/exp_base_document_layout_fonts/static/src/fonts/DroidKufi-Regular.eot b/exp_base_document_layout_fonts/static/src/fonts/DroidKufi-Regular.eot
new file mode 100644
index 0000000..d29fcdc
Binary files /dev/null and b/exp_base_document_layout_fonts/static/src/fonts/DroidKufi-Regular.eot differ
diff --git a/exp_base_document_layout_fonts/static/src/fonts/DroidKufi-Regular.ttf b/exp_base_document_layout_fonts/static/src/fonts/DroidKufi-Regular.ttf
new file mode 100644
index 0000000..af85975
Binary files /dev/null and b/exp_base_document_layout_fonts/static/src/fonts/DroidKufi-Regular.ttf differ
diff --git a/exp_base_document_layout_fonts/static/src/fonts/DroidKufi-Regular.woff b/exp_base_document_layout_fonts/static/src/fonts/DroidKufi-Regular.woff
new file mode 100644
index 0000000..2c328bb
Binary files /dev/null and b/exp_base_document_layout_fonts/static/src/fonts/DroidKufi-Regular.woff differ
diff --git a/exp_base_document_layout_fonts/static/src/fonts/DroidKufi-Regular.woff2 b/exp_base_document_layout_fonts/static/src/fonts/DroidKufi-Regular.woff2
new file mode 100644
index 0000000..44cd1a9
Binary files /dev/null and b/exp_base_document_layout_fonts/static/src/fonts/DroidKufi-Regular.woff2 differ
diff --git a/exp_base_document_layout_fonts/static/src/fonts/DroidNaskh-Bold.eot b/exp_base_document_layout_fonts/static/src/fonts/DroidNaskh-Bold.eot
new file mode 100644
index 0000000..be6a9ab
Binary files /dev/null and b/exp_base_document_layout_fonts/static/src/fonts/DroidNaskh-Bold.eot differ
diff --git a/exp_base_document_layout_fonts/static/src/fonts/DroidNaskh-Bold.ttf b/exp_base_document_layout_fonts/static/src/fonts/DroidNaskh-Bold.ttf
new file mode 100644
index 0000000..692b796
Binary files /dev/null and b/exp_base_document_layout_fonts/static/src/fonts/DroidNaskh-Bold.ttf differ
diff --git a/exp_base_document_layout_fonts/static/src/fonts/DroidNaskh-Bold.woff b/exp_base_document_layout_fonts/static/src/fonts/DroidNaskh-Bold.woff
new file mode 100644
index 0000000..61c4ce6
Binary files /dev/null and b/exp_base_document_layout_fonts/static/src/fonts/DroidNaskh-Bold.woff differ
diff --git a/exp_base_document_layout_fonts/static/src/fonts/DroidNaskh-Bold.woff2 b/exp_base_document_layout_fonts/static/src/fonts/DroidNaskh-Bold.woff2
new file mode 100644
index 0000000..a480760
Binary files /dev/null and b/exp_base_document_layout_fonts/static/src/fonts/DroidNaskh-Bold.woff2 differ
diff --git a/exp_base_document_layout_fonts/static/src/fonts/DroidNaskh-Regular.eot b/exp_base_document_layout_fonts/static/src/fonts/DroidNaskh-Regular.eot
new file mode 100644
index 0000000..0021336
Binary files /dev/null and b/exp_base_document_layout_fonts/static/src/fonts/DroidNaskh-Regular.eot differ
diff --git a/exp_base_document_layout_fonts/static/src/fonts/DroidNaskh-Regular.ttf b/exp_base_document_layout_fonts/static/src/fonts/DroidNaskh-Regular.ttf
new file mode 100644
index 0000000..da9a45f
Binary files /dev/null and b/exp_base_document_layout_fonts/static/src/fonts/DroidNaskh-Regular.ttf differ
diff --git a/exp_base_document_layout_fonts/static/src/fonts/DroidNaskh-Regular.woff b/exp_base_document_layout_fonts/static/src/fonts/DroidNaskh-Regular.woff
new file mode 100644
index 0000000..7726404
Binary files /dev/null and b/exp_base_document_layout_fonts/static/src/fonts/DroidNaskh-Regular.woff differ
diff --git a/exp_base_document_layout_fonts/static/src/fonts/DroidNaskh-Regular.woff2 b/exp_base_document_layout_fonts/static/src/fonts/DroidNaskh-Regular.woff2
new file mode 100644
index 0000000..a5fd31b
Binary files /dev/null and b/exp_base_document_layout_fonts/static/src/fonts/DroidNaskh-Regular.woff2 differ
diff --git a/exp_base_document_layout_fonts/static/src/fonts/bukrabold.otf b/exp_base_document_layout_fonts/static/src/fonts/bukrabold.otf
new file mode 100644
index 0000000..09046c8
Binary files /dev/null and b/exp_base_document_layout_fonts/static/src/fonts/bukrabold.otf differ
diff --git a/exp_base_document_layout_fonts/static/src/fonts/bukrabold.ttf b/exp_base_document_layout_fonts/static/src/fonts/bukrabold.ttf
new file mode 100644
index 0000000..e998153
Binary files /dev/null and b/exp_base_document_layout_fonts/static/src/fonts/bukrabold.ttf differ
diff --git a/exp_base_document_layout_fonts/static/src/fonts/bukralight.ttf b/exp_base_document_layout_fonts/static/src/fonts/bukralight.ttf
new file mode 100644
index 0000000..1c9c6b1
Binary files /dev/null and b/exp_base_document_layout_fonts/static/src/fonts/bukralight.ttf differ
diff --git a/exp_base_document_layout_fonts/static/src/fonts/bukraregular.otf b/exp_base_document_layout_fonts/static/src/fonts/bukraregular.otf
new file mode 100644
index 0000000..4e447f0
Binary files /dev/null and b/exp_base_document_layout_fonts/static/src/fonts/bukraregular.otf differ
diff --git a/exp_base_document_layout_fonts/static/src/scss/fonts.scss b/exp_base_document_layout_fonts/static/src/scss/fonts.scss
new file mode 100644
index 0000000..21efc61
--- /dev/null
+++ b/exp_base_document_layout_fonts/static/src/scss/fonts.scss
@@ -0,0 +1,68 @@
+@font-face {
+ font-family: "Bukra";
+ font-style: normal;
+ font-weight: 400;
+ src: url(/exp_base_document_layout_fonts/static/src/fonts/bukraregular.otf)
+ format("opentype"),
+ url(/exp_base_document_layout_fonts/static/src/fonts/bukralight.ttf)
+ format("truetype");
+}
+
+@font-face {
+ font-family: "Bukra";
+ font-style: normal;
+ font-weight: 700;
+ src: url(/exp_base_document_layout_fonts/static/src/fonts/bukrabold.otf)
+ format("opentype"),
+ url(/exp_base_document_layout_fonts/static/src/fonts/bukrabold.ttf)
+ format("truetype");
+}
+
+@font-face {
+ font-family: "DroidKufi";
+ font-style: normal;
+ font-weight: 400;
+ src: url(/exp_base_document_layout_fonts/static/src/fonts/DroidKufi-Regular.eot);
+ src: url(/exp_base_document_layout_fonts/static/src/fonts/DroidKufi-Regular.woff2)
+ format("woff2"),
+ url(/exp_base_document_layout_fonts/static/src/fonts/DroidKufi-Regular.woff)
+ format("woff"),
+ url(/exp_base_document_layout_fonts/static/src/fonts/DroidKufi-Regular.ttf)
+ format("truetype");
+}
+@font-face {
+ font-family: "DroidKufi";
+ font-style: normal;
+ font-weight: 700;
+ src: url(/exp_base_document_layout_fonts/static/src/fonts/DroidKufi-Bold.eot);
+ src: url(/exp_base_document_layout_fonts/static/src/fonts/DroidKufi-Bold.woff2)
+ format("woff2"),
+ url(/exp_base_document_layout_fonts/static/src/fonts/DroidKufi-Bold.woff)
+ format("woff"),
+ url(/exp_base_document_layout_fonts/static/src/fonts/DroidKufi-Bold.ttf)
+ format("truetype");
+}
+@font-face {
+ font-family: "DroidNaskh";
+ font-style: normal;
+ font-weight: 400;
+ src: url(/exp_base_document_layout_fonts/static/src/fonts/DroidNaskh-Regular.eot);
+ src: url(/exp_base_document_layout_fonts/static/src/fonts/DroidNaskh-Regular.woff2)
+ format("woff2"),
+ url(/exp_base_document_layout_fonts/static/src/fonts/DroidNaskh-Regular.woff)
+ format("woff"),
+ url(/exp_base_document_layout_fonts/static/src/fonts/DroidNaskh-Regular.ttf)
+ format("truetype");
+}
+@font-face {
+ font-family: "DroidNaskh";
+ font-style: normal;
+ font-weight: 700;
+ src: url(/exp_base_document_layout_fonts/static/src/fonts/DroidNaskh-Bold.eot);
+ src: url(/exp_base_document_layout_fonts/static/src/fonts/DroidNaskh-Bold.woff2)
+ format("woff2"),
+ url(/exp_base_document_layout_fonts/static/src/fonts/DroidNaskh-Bold.woff)
+ format("woff"),
+ url(/exp_base_document_layout_fonts/static/src/fonts/DroidNaskh-Bold.ttf)
+ format("truetype");
+}
diff --git a/exp_base_document_layout_fonts/views/webclient.xml b/exp_base_document_layout_fonts/views/webclient.xml
new file mode 100644
index 0000000..8a823a3
--- /dev/null
+++ b/exp_base_document_layout_fonts/views/webclient.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/expert_font_for_website/__init__.py b/expert_font_for_website/__init__.py
new file mode 100644
index 0000000..511a0ca
--- /dev/null
+++ b/expert_font_for_website/__init__.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8 -*-
+
+from . import controllers
+from . import models
\ No newline at end of file
diff --git a/expert_font_for_website/__manifest__.py b/expert_font_for_website/__manifest__.py
new file mode 100644
index 0000000..9bdb553
--- /dev/null
+++ b/expert_font_for_website/__manifest__.py
@@ -0,0 +1,27 @@
+# -*- coding: utf-8 -*-
+{
+ "name": "Expert Font For Website",
+ "summary": "Customization Module For Expert Font",
+ "description": "Expert Font For Website",
+ "author": "Expert Co. Ltd.",
+ "website": "http://www.exp-sa.com",
+ "category": "Tools",
+ "version": "18.0.1.0.0", # updated for Odoo 18
+ "depends": ["web"],
+ "data": [
+ # "security/ir.model.access.csv",
+ # "views/resources.xml",
+ ],
+ "demo": [
+ # "demo/demo.xml",
+ ],
+ "assets": {
+ "web.assets_backend": [
+ "expert_font_for_website/static/src/css/custom_rtl.css",
+ "expert_font_for_website/static/src/css/footer.css",
+ ],
+ },
+ "license": "LGPL-3",
+ "installable": True,
+ "application": False,
+}
diff --git a/expert_font_for_website/controllers/__init__.py b/expert_font_for_website/controllers/__init__.py
new file mode 100644
index 0000000..457bae2
--- /dev/null
+++ b/expert_font_for_website/controllers/__init__.py
@@ -0,0 +1,3 @@
+# -*- coding: utf-8 -*-
+
+from . import controllers
\ No newline at end of file
diff --git a/expert_font_for_website/controllers/controllers.py b/expert_font_for_website/controllers/controllers.py
new file mode 100644
index 0000000..f7fedfe
--- /dev/null
+++ b/expert_font_for_website/controllers/controllers.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+from odoo import http
+
+# class StandardCustomTheme(http.Controller):
+# @http.route('/standard_custom_theme/standard_custom_theme/', auth='public')
+# def index(self, **kw):
+# return "Hello, world"
+
+# @http.route('/standard_custom_theme/standard_custom_theme/objects/', auth='public')
+# def list(self, **kw):
+# return http.request.render('standard_custom_theme.listing', {
+# 'root': '/standard_custom_theme/standard_custom_theme',
+# 'objects': http.request.env['standard_custom_theme.standard_custom_theme'].search([]),
+# })
+
+# @http.route('/standard_custom_theme/standard_custom_theme/objects//', auth='public')
+# def object(self, obj, **kw):
+# return http.request.render('standard_custom_theme.object', {
+# 'object': obj
+# })
\ No newline at end of file
diff --git a/expert_font_for_website/demo/demo.xml b/expert_font_for_website/demo/demo.xml
new file mode 100644
index 0000000..f7bcabd
--- /dev/null
+++ b/expert_font_for_website/demo/demo.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/expert_font_for_website/models/__init__.py b/expert_font_for_website/models/__init__.py
new file mode 100644
index 0000000..5305644
--- /dev/null
+++ b/expert_font_for_website/models/__init__.py
@@ -0,0 +1,3 @@
+# -*- coding: utf-8 -*-
+
+from . import models
\ No newline at end of file
diff --git a/expert_font_for_website/models/models.py b/expert_font_for_website/models/models.py
new file mode 100644
index 0000000..d624c84
--- /dev/null
+++ b/expert_font_for_website/models/models.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from odoo import models, fields, api
+
+# class standard_custom_theme(models.Model):
+# _name = 'standard_custom_theme.standard_custom_theme'
+
+# name = fields.Char()
+# value = fields.Integer()
+# value2 = fields.Float(compute="_value_pc", store=True)
+# description = fields.Text()
+#
+# @api.depends('value')
+# def _value_pc(self):
+# self.value2 = float(self.value) / 100
\ No newline at end of file
diff --git a/expert_font_for_website/security/ir.model.access.csv b/expert_font_for_website/security/ir.model.access.csv
new file mode 100644
index 0000000..1e36e1c
--- /dev/null
+++ b/expert_font_for_website/security/ir.model.access.csv
@@ -0,0 +1,2 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+access_standard_custom_theme_standard_custom_theme,standard_custom_theme.standard_custom_theme,model_standard_custom_theme_standard_custom_theme,,1,0,0,0
\ No newline at end of file
diff --git a/expert_font_for_website/static/src/css/custom_rtl.css b/expert_font_for_website/static/src/css/custom_rtl.css
new file mode 100644
index 0000000..0e97bc3
--- /dev/null
+++ b/expert_font_for_website/static/src/css/custom_rtl.css
@@ -0,0 +1,35 @@
+@font-face {
+ font-family: "Droid Arabic Kufi";
+ font-style: normal;
+ font-weight: 400;
+ src: url(/expert_font_for_website/static/src/fonts/DroidKufi-Regular.eot);
+ src: url(/expert_font_for_website/static/src/fonts/DroidKufi-Regular.woff2) format("woff2"), url(/expert_font_for_website/static/src/fonts/DroidKufi-Regular.woff) format("woff"), url(/expert_font_for_website/static/src/fonts/DroidKufi-Regular.ttf) format("truetype");
+}
+@font-face {
+ font-family: "Droid Arabic Kufi";
+ font-style: normal;
+ font-weight: 700;
+ src: url(/expert_font_for_website/static/src/fonts/DroidKufi-Bold.eot);
+ src: url(/expert_font_for_website/static/src/fonts/DroidKufi-Bold.woff2) format("woff2"), url(/expert_font_for_website/static/src/fonts/DroidKufi-Bold.woff) format("woff"), url(/expert_font_for_website/static/src/fonts/DroidKufi-Bold.ttf) format("truetype");
+}
+@font-face {
+ font-family: "Droid Arabic Naskh";
+ font-style: normal;
+ font-weight: 400;
+ src: url(/expert_font_for_website/static/src/fonts/DroidNaskh-Regular.eot);
+ src: url(/expert_font_for_website/static/src/fonts/DroidNaskh-Regular.woff2) format("woff2"), url(/expert_font_for_website/static/src/fonts/DroidNaskh-Regular.woff) format("woff"), url(/expert_font_for_website/static/src/fonts/DroidNaskh-Regular.ttf) format("truetype");
+}
+@font-face {
+ font-family: "Droid Arabic Naskh";
+ font-style: normal;
+ font-weight: 700;
+ src: url(/expert_font_for_website/static/src/fonts/DroidNaskh-Bold.eot);
+ src: url(/expert_font_for_website/static/src/fonts/DroidNaskh-Bold.woff2) format("woff2"), url(/expert_font_for_website/static/src/fonts/DroidNaskh-Bold.woff) format("woff"), url(/expert_font_for_website/static/src/fonts/DroidNaskh-Bold.ttf) format("truetype");
+}
+.rtl *:not(.fa) {
+ font-family: "Droid Arabic Kufi", serif !important;
+}
+
+.o_rtl *:not(.fa) {
+ font-family: "Droid Arabic Kufi", serif !important;
+}/*# sourceMappingURL=custom_rtl.css.map */
\ No newline at end of file
diff --git a/expert_font_for_website/static/src/css/custom_rtl.css.map b/expert_font_for_website/static/src/css/custom_rtl.css.map
new file mode 100644
index 0000000..4d9a318
--- /dev/null
+++ b/expert_font_for_website/static/src/css/custom_rtl.css.map
@@ -0,0 +1 @@
+{"version":3,"sources":["custom_rtl.scss","custom_rtl.css"],"names":[],"mappings":"AAAA;EACI,gCAAA;EACA,kBAAA;EACA,gBAAA;EACA,yEAAA;EACA,0QAAA;ACCJ;ADIA;EACI,gCAAA;EACA,kBAAA;EACA,gBAAA;EACA,sEAAA;EACA,iQAAA;ACFJ;ADOA;EACI,iCAAA;EACA,kBAAA;EACA,gBAAA;EACA,0EAAA;EACA,6QAAA;ACLJ;ADUA;EACI,iCAAA;EACA,kBAAA;EACA,gBAAA;EACA,uEAAA;EACA,oQAAA;ACRJ;ADaI;EACI,kDAAA;ACXR;;ADeI;EACI,kDAAA;ACZR","file":"custom_rtl.css"}
\ No newline at end of file
diff --git a/expert_font_for_website/static/src/css/custom_rtl.scss b/expert_font_for_website/static/src/css/custom_rtl.scss
new file mode 100644
index 0000000..8bf49c8
--- /dev/null
+++ b/expert_font_for_website/static/src/css/custom_rtl.scss
@@ -0,0 +1,49 @@
+@font-face {
+ font-family: 'Droid Arabic Kufi';
+ font-style: normal;
+ font-weight: 400;
+ src: url(/expert_font_for_website/static/src/fonts/DroidKufi-Regular.eot);
+ src: url(/expert_font_for_website/static/src/fonts/DroidKufi-Regular.woff2) format('woff2'),
+ url(/expert_font_for_website/static/src/fonts/DroidKufi-Regular.woff) format('woff'),
+ url(/expert_font_for_website/static/src/fonts/DroidKufi-Regular.ttf) format('truetype');
+}
+
+@font-face {
+ font-family: 'Droid Arabic Kufi';
+ font-style: normal;
+ font-weight: 700;
+ src: url(/expert_font_for_website/static/src/fonts/DroidKufi-Bold.eot);
+ src: url(/expert_font_for_website/static/src/fonts/DroidKufi-Bold.woff2) format('woff2'),
+ url(/expert_font_for_website/static/src/fonts/DroidKufi-Bold.woff) format('woff'),
+ url(/expert_font_for_website/static/src/fonts/DroidKufi-Bold.ttf) format('truetype');
+}
+
+@font-face {
+ font-family: 'Droid Arabic Naskh';
+ font-style: normal;
+ font-weight: 400;
+ src: url(/expert_font_for_website/static/src/fonts/DroidNaskh-Regular.eot);
+ src: url(/expert_font_for_website/static/src/fonts/DroidNaskh-Regular.woff2) format('woff2'),
+ url(/expert_font_for_website/static/src/fonts/DroidNaskh-Regular.woff) format('woff'),
+ url(/expert_font_for_website/static/src/fonts/DroidNaskh-Regular.ttf) format('truetype');
+}
+
+@font-face {
+ font-family: 'Droid Arabic Naskh';
+ font-style: normal;
+ font-weight: 700;
+ src: url(/expert_font_for_website/static/src/fonts/DroidNaskh-Bold.eot);
+ src: url(/expert_font_for_website/static/src/fonts/DroidNaskh-Bold.woff2) format('woff2'),
+ url(/expert_font_for_website/static/src/fonts/DroidNaskh-Bold.woff) format('woff'),
+ url(/expert_font_for_website/static/src/fonts/DroidNaskh-Bold.ttf) format('truetype');
+}
+.rtl{
+ *:not(.fa) {
+ font-family: 'Droid Arabic Kufi', serif !important;
+ }
+}
+.o_rtl{
+ *:not(.fa) {
+ font-family: 'Droid Arabic Kufi', serif !important;
+ }
+}
\ No newline at end of file
diff --git a/expert_font_for_website/static/src/css/footer.css b/expert_font_for_website/static/src/css/footer.css
new file mode 100644
index 0000000..4025f77
--- /dev/null
+++ b/expert_font_for_website/static/src/css/footer.css
@@ -0,0 +1,3 @@
+.o_brand_promotion {
+ display: none !important;
+}/*# sourceMappingURL=footer.css.map */
\ No newline at end of file
diff --git a/expert_font_for_website/static/src/css/footer.css.map b/expert_font_for_website/static/src/css/footer.css.map
new file mode 100644
index 0000000..37a3e0c
--- /dev/null
+++ b/expert_font_for_website/static/src/css/footer.css.map
@@ -0,0 +1 @@
+{"version":3,"sources":["footer.scss","footer.css"],"names":[],"mappings":"AAAA;EACI,wBAAA;ACCJ","file":"footer.css"}
\ No newline at end of file
diff --git a/expert_font_for_website/static/src/css/footer.scss b/expert_font_for_website/static/src/css/footer.scss
new file mode 100644
index 0000000..825cc61
--- /dev/null
+++ b/expert_font_for_website/static/src/css/footer.scss
@@ -0,0 +1,3 @@
+.o_brand_promotion{
+ display: none!important;
+}
\ No newline at end of file
diff --git a/expert_font_for_website/static/src/fonts/DroidKufi-Bold.eot b/expert_font_for_website/static/src/fonts/DroidKufi-Bold.eot
new file mode 100644
index 0000000..c98ced3
Binary files /dev/null and b/expert_font_for_website/static/src/fonts/DroidKufi-Bold.eot differ
diff --git a/expert_font_for_website/static/src/fonts/DroidKufi-Bold.ttf b/expert_font_for_website/static/src/fonts/DroidKufi-Bold.ttf
new file mode 100644
index 0000000..650919e
Binary files /dev/null and b/expert_font_for_website/static/src/fonts/DroidKufi-Bold.ttf differ
diff --git a/expert_font_for_website/static/src/fonts/DroidKufi-Bold.woff b/expert_font_for_website/static/src/fonts/DroidKufi-Bold.woff
new file mode 100644
index 0000000..565c003
Binary files /dev/null and b/expert_font_for_website/static/src/fonts/DroidKufi-Bold.woff differ
diff --git a/expert_font_for_website/static/src/fonts/DroidKufi-Bold.woff2 b/expert_font_for_website/static/src/fonts/DroidKufi-Bold.woff2
new file mode 100644
index 0000000..27f95d0
Binary files /dev/null and b/expert_font_for_website/static/src/fonts/DroidKufi-Bold.woff2 differ
diff --git a/expert_font_for_website/static/src/fonts/DroidKufi-Regular.eot b/expert_font_for_website/static/src/fonts/DroidKufi-Regular.eot
new file mode 100644
index 0000000..d29fcdc
Binary files /dev/null and b/expert_font_for_website/static/src/fonts/DroidKufi-Regular.eot differ
diff --git a/expert_font_for_website/static/src/fonts/DroidKufi-Regular.ttf b/expert_font_for_website/static/src/fonts/DroidKufi-Regular.ttf
new file mode 100644
index 0000000..af85975
Binary files /dev/null and b/expert_font_for_website/static/src/fonts/DroidKufi-Regular.ttf differ
diff --git a/expert_font_for_website/static/src/fonts/DroidKufi-Regular.woff b/expert_font_for_website/static/src/fonts/DroidKufi-Regular.woff
new file mode 100644
index 0000000..2c328bb
Binary files /dev/null and b/expert_font_for_website/static/src/fonts/DroidKufi-Regular.woff differ
diff --git a/expert_font_for_website/static/src/fonts/DroidKufi-Regular.woff2 b/expert_font_for_website/static/src/fonts/DroidKufi-Regular.woff2
new file mode 100644
index 0000000..44cd1a9
Binary files /dev/null and b/expert_font_for_website/static/src/fonts/DroidKufi-Regular.woff2 differ
diff --git a/expert_font_for_website/static/src/fonts/DroidNaskh-Bold.eot b/expert_font_for_website/static/src/fonts/DroidNaskh-Bold.eot
new file mode 100644
index 0000000..be6a9ab
Binary files /dev/null and b/expert_font_for_website/static/src/fonts/DroidNaskh-Bold.eot differ
diff --git a/expert_font_for_website/static/src/fonts/DroidNaskh-Bold.ttf b/expert_font_for_website/static/src/fonts/DroidNaskh-Bold.ttf
new file mode 100644
index 0000000..692b796
Binary files /dev/null and b/expert_font_for_website/static/src/fonts/DroidNaskh-Bold.ttf differ
diff --git a/expert_font_for_website/static/src/fonts/DroidNaskh-Bold.woff b/expert_font_for_website/static/src/fonts/DroidNaskh-Bold.woff
new file mode 100644
index 0000000..61c4ce6
Binary files /dev/null and b/expert_font_for_website/static/src/fonts/DroidNaskh-Bold.woff differ
diff --git a/expert_font_for_website/static/src/fonts/DroidNaskh-Bold.woff2 b/expert_font_for_website/static/src/fonts/DroidNaskh-Bold.woff2
new file mode 100644
index 0000000..a480760
Binary files /dev/null and b/expert_font_for_website/static/src/fonts/DroidNaskh-Bold.woff2 differ
diff --git a/expert_font_for_website/static/src/fonts/DroidNaskh-Regular.eot b/expert_font_for_website/static/src/fonts/DroidNaskh-Regular.eot
new file mode 100644
index 0000000..0021336
Binary files /dev/null and b/expert_font_for_website/static/src/fonts/DroidNaskh-Regular.eot differ
diff --git a/expert_font_for_website/static/src/fonts/DroidNaskh-Regular.ttf b/expert_font_for_website/static/src/fonts/DroidNaskh-Regular.ttf
new file mode 100644
index 0000000..da9a45f
Binary files /dev/null and b/expert_font_for_website/static/src/fonts/DroidNaskh-Regular.ttf differ
diff --git a/expert_font_for_website/static/src/fonts/DroidNaskh-Regular.woff b/expert_font_for_website/static/src/fonts/DroidNaskh-Regular.woff
new file mode 100644
index 0000000..7726404
Binary files /dev/null and b/expert_font_for_website/static/src/fonts/DroidNaskh-Regular.woff differ
diff --git a/expert_font_for_website/static/src/fonts/DroidNaskh-Regular.woff2 b/expert_font_for_website/static/src/fonts/DroidNaskh-Regular.woff2
new file mode 100644
index 0000000..a5fd31b
Binary files /dev/null and b/expert_font_for_website/static/src/fonts/DroidNaskh-Regular.woff2 differ
diff --git a/expert_font_for_website/views/resources.xml b/expert_font_for_website/views/resources.xml
new file mode 100644
index 0000000..d812eb9
--- /dev/null
+++ b/expert_font_for_website/views/resources.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/hide_login_db_selection/__init__.py b/hide_login_db_selection/__init__.py
new file mode 100644
index 0000000..511a0ca
--- /dev/null
+++ b/hide_login_db_selection/__init__.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8 -*-
+
+from . import controllers
+from . import models
\ No newline at end of file
diff --git a/hide_login_db_selection/__manifest__.py b/hide_login_db_selection/__manifest__.py
new file mode 100644
index 0000000..fe81c10
--- /dev/null
+++ b/hide_login_db_selection/__manifest__.py
@@ -0,0 +1,26 @@
+# -*- coding: utf-8 -*-
+{
+ 'name': "Hide Portal Login DB Selection",
+ 'summary': "Customization for Backend Themes built for Portal Login DB Selection",
+ 'description': "Hide Portal Login DB Selection",
+ 'author': "Expert Co. Ltd.",
+ 'website': "http://www.exp-sa.com",
+ 'category': 'Odex25-base',
+ 'version': '18.0.1.0.0',
+ 'depends': ['web', 'odex25_website'],
+ 'data': [
+ # 'security/ir.model.access.csv',
+ # no need for resources.xml anymore
+ ],
+ 'assets': {
+ 'web.assets_backend': [
+ "hide_login_db_selection/static/src/css/database-hide.css",
+ "hide_login_db_selection/static/js/login_page.js",
+ ],
+ },
+ 'demo': [
+ 'demo/demo.xml',
+ ],
+ 'installable': True,
+ 'application': False,
+}
diff --git a/hide_login_db_selection/controllers/__init__.py b/hide_login_db_selection/controllers/__init__.py
new file mode 100644
index 0000000..457bae2
--- /dev/null
+++ b/hide_login_db_selection/controllers/__init__.py
@@ -0,0 +1,3 @@
+# -*- coding: utf-8 -*-
+
+from . import controllers
\ No newline at end of file
diff --git a/hide_login_db_selection/controllers/__pycache__/__init__.cpython-38.pyc b/hide_login_db_selection/controllers/__pycache__/__init__.cpython-38.pyc
new file mode 100644
index 0000000..105cf51
Binary files /dev/null and b/hide_login_db_selection/controllers/__pycache__/__init__.cpython-38.pyc differ
diff --git a/hide_login_db_selection/controllers/__pycache__/controllers.cpython-38.pyc b/hide_login_db_selection/controllers/__pycache__/controllers.cpython-38.pyc
new file mode 100644
index 0000000..4652458
Binary files /dev/null and b/hide_login_db_selection/controllers/__pycache__/controllers.cpython-38.pyc differ
diff --git a/hide_login_db_selection/controllers/controllers.py b/hide_login_db_selection/controllers/controllers.py
new file mode 100644
index 0000000..f7fedfe
--- /dev/null
+++ b/hide_login_db_selection/controllers/controllers.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+from odoo import http
+
+# class StandardCustomTheme(http.Controller):
+# @http.route('/standard_custom_theme/standard_custom_theme/', auth='public')
+# def index(self, **kw):
+# return "Hello, world"
+
+# @http.route('/standard_custom_theme/standard_custom_theme/objects/', auth='public')
+# def list(self, **kw):
+# return http.request.render('standard_custom_theme.listing', {
+# 'root': '/standard_custom_theme/standard_custom_theme',
+# 'objects': http.request.env['standard_custom_theme.standard_custom_theme'].search([]),
+# })
+
+# @http.route('/standard_custom_theme/standard_custom_theme/objects//', auth='public')
+# def object(self, obj, **kw):
+# return http.request.render('standard_custom_theme.object', {
+# 'object': obj
+# })
\ No newline at end of file
diff --git a/hide_login_db_selection/demo/demo.xml b/hide_login_db_selection/demo/demo.xml
new file mode 100644
index 0000000..f7bcabd
--- /dev/null
+++ b/hide_login_db_selection/demo/demo.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/hide_login_db_selection/models/__init__.py b/hide_login_db_selection/models/__init__.py
new file mode 100644
index 0000000..5305644
--- /dev/null
+++ b/hide_login_db_selection/models/__init__.py
@@ -0,0 +1,3 @@
+# -*- coding: utf-8 -*-
+
+from . import models
\ No newline at end of file
diff --git a/hide_login_db_selection/models/__pycache__/__init__.cpython-38.pyc b/hide_login_db_selection/models/__pycache__/__init__.cpython-38.pyc
new file mode 100644
index 0000000..a3d73f5
Binary files /dev/null and b/hide_login_db_selection/models/__pycache__/__init__.cpython-38.pyc differ
diff --git a/hide_login_db_selection/models/__pycache__/models.cpython-38.pyc b/hide_login_db_selection/models/__pycache__/models.cpython-38.pyc
new file mode 100644
index 0000000..54521cd
Binary files /dev/null and b/hide_login_db_selection/models/__pycache__/models.cpython-38.pyc differ
diff --git a/hide_login_db_selection/models/models.py b/hide_login_db_selection/models/models.py
new file mode 100644
index 0000000..d624c84
--- /dev/null
+++ b/hide_login_db_selection/models/models.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from odoo import models, fields, api
+
+# class standard_custom_theme(models.Model):
+# _name = 'standard_custom_theme.standard_custom_theme'
+
+# name = fields.Char()
+# value = fields.Integer()
+# value2 = fields.Float(compute="_value_pc", store=True)
+# description = fields.Text()
+#
+# @api.depends('value')
+# def _value_pc(self):
+# self.value2 = float(self.value) / 100
\ No newline at end of file
diff --git a/hide_login_db_selection/security/ir.model.access.csv b/hide_login_db_selection/security/ir.model.access.csv
new file mode 100644
index 0000000..1e36e1c
--- /dev/null
+++ b/hide_login_db_selection/security/ir.model.access.csv
@@ -0,0 +1,2 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+access_standard_custom_theme_standard_custom_theme,standard_custom_theme.standard_custom_theme,model_standard_custom_theme_standard_custom_theme,,1,0,0,0
\ No newline at end of file
diff --git a/hide_login_db_selection/static/img/icon.png b/hide_login_db_selection/static/img/icon.png
new file mode 100644
index 0000000..a37b596
Binary files /dev/null and b/hide_login_db_selection/static/img/icon.png differ
diff --git a/hide_login_db_selection/static/img/index.html b/hide_login_db_selection/static/img/index.html
new file mode 100644
index 0000000..895109b
--- /dev/null
+++ b/hide_login_db_selection/static/img/index.html
@@ -0,0 +1,83 @@
+
+
+
+ ONE OF ODEX MODULES
+
+ ODEX system is over than 200+ modules developed by love of Expert Company, based on ODOO system
+
+ .to effectively suite's Saudi and Arabic market needs.It is the first Arabic open source ERP and all-in-one
+ solution
+
+
+
+
+
+
+
diff --git a/hide_login_db_selection/static/img/internet.png b/hide_login_db_selection/static/img/internet.png
new file mode 100644
index 0000000..a89809b
Binary files /dev/null and b/hide_login_db_selection/static/img/internet.png differ
diff --git a/hide_login_db_selection/static/img/linkedin.png b/hide_login_db_selection/static/img/linkedin.png
new file mode 100644
index 0000000..a0fe09c
Binary files /dev/null and b/hide_login_db_selection/static/img/linkedin.png differ
diff --git a/hide_login_db_selection/static/img/mail.png b/hide_login_db_selection/static/img/mail.png
new file mode 100644
index 0000000..bc5a4de
Binary files /dev/null and b/hide_login_db_selection/static/img/mail.png differ
diff --git a/hide_login_db_selection/static/img/odex.png b/hide_login_db_selection/static/img/odex.png
new file mode 100644
index 0000000..de82c0e
Binary files /dev/null and b/hide_login_db_selection/static/img/odex.png differ
diff --git a/hide_login_db_selection/static/img/smiling_face.svg b/hide_login_db_selection/static/img/smiling_face.svg
new file mode 100644
index 0000000..250900e
--- /dev/null
+++ b/hide_login_db_selection/static/img/smiling_face.svg
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/hide_login_db_selection/static/img/twitter.png b/hide_login_db_selection/static/img/twitter.png
new file mode 100644
index 0000000..983f325
Binary files /dev/null and b/hide_login_db_selection/static/img/twitter.png differ
diff --git a/hide_login_db_selection/static/js/login_page.js b/hide_login_db_selection/static/js/login_page.js
new file mode 100644
index 0000000..1a86503
--- /dev/null
+++ b/hide_login_db_selection/static/js/login_page.js
@@ -0,0 +1,8 @@
+$(document).ready(function () {
+
+ if (window.location.pathname.match(/^\/web\/login/)) {
+ $("body").addClass("login_page")
+ };
+
+});
+
diff --git a/hide_login_db_selection/static/src/css/database-hide.css b/hide_login_db_selection/static/src/css/database-hide.css
new file mode 100644
index 0000000..66ffc47
--- /dev/null
+++ b/hide_login_db_selection/static/src/css/database-hide.css
@@ -0,0 +1,3 @@
+.login_page #wrapwrap main .oe_website_login_container .oe_login_form .field-db {
+ display: none !important;
+}/*# sourceMappingURL=database-hide.css.map */
\ No newline at end of file
diff --git a/hide_login_db_selection/static/src/css/database-hide.css.map b/hide_login_db_selection/static/src/css/database-hide.css.map
new file mode 100644
index 0000000..045e9b0
--- /dev/null
+++ b/hide_login_db_selection/static/src/css/database-hide.css.map
@@ -0,0 +1 @@
+{"version":3,"sources":["database-hide.scss","database-hide.css"],"names":[],"mappings":"AAKoB;EACI,wBAAA;ACJxB","file":"database-hide.css"}
\ No newline at end of file
diff --git a/hide_login_db_selection/static/src/css/database-hide.scss b/hide_login_db_selection/static/src/css/database-hide.scss
new file mode 100644
index 0000000..94e82ff
--- /dev/null
+++ b/hide_login_db_selection/static/src/css/database-hide.scss
@@ -0,0 +1,13 @@
+.login_page{
+ #wrapwrap{
+ main{
+ .oe_website_login_container{
+ .oe_login_form{
+ .field-db{
+ display: none!important;
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/hide_login_db_selection/views/resources.xml b/hide_login_db_selection/views/resources.xml
new file mode 100644
index 0000000..4a77a5d
--- /dev/null
+++ b/hide_login_db_selection/views/resources.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/inbox_notif_email/.idea/.gitignore b/inbox_notif_email/.idea/.gitignore
new file mode 100644
index 0000000..3cb95ef
--- /dev/null
+++ b/inbox_notif_email/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Datasource local storage ignored files
+/../../../../../../../:\Users\Adnan Usmani\Downloads\Compressed\inbox_notif_email\.idea/dataSources/
+/dataSources.local.xml
+# Editor-based HTTP Client requests
+/httpRequests/
diff --git a/inbox_notif_email/.idea/inbox_notif_email.iml b/inbox_notif_email/.idea/inbox_notif_email.iml
new file mode 100644
index 0000000..92b8cab
--- /dev/null
+++ b/inbox_notif_email/.idea/inbox_notif_email.iml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/inbox_notif_email/.idea/inspectionProfiles/Project_Default.xml b/inbox_notif_email/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..a5550a3
--- /dev/null
+++ b/inbox_notif_email/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/inbox_notif_email/.idea/inspectionProfiles/profiles_settings.xml b/inbox_notif_email/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/inbox_notif_email/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/inbox_notif_email/.idea/misc.xml b/inbox_notif_email/.idea/misc.xml
new file mode 100644
index 0000000..d1e22ec
--- /dev/null
+++ b/inbox_notif_email/.idea/misc.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/inbox_notif_email/.idea/modules.xml b/inbox_notif_email/.idea/modules.xml
new file mode 100644
index 0000000..ce31c98
--- /dev/null
+++ b/inbox_notif_email/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/inbox_notif_email/.idea/vcs.xml b/inbox_notif_email/.idea/vcs.xml
new file mode 100644
index 0000000..6c0b863
--- /dev/null
+++ b/inbox_notif_email/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/inbox_notif_email/__init__.py b/inbox_notif_email/__init__.py
new file mode 100644
index 0000000..511a0ca
--- /dev/null
+++ b/inbox_notif_email/__init__.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8 -*-
+
+from . import controllers
+from . import models
\ No newline at end of file
diff --git a/inbox_notif_email/__manifest__.py b/inbox_notif_email/__manifest__.py
new file mode 100644
index 0000000..71edf9d
--- /dev/null
+++ b/inbox_notif_email/__manifest__.py
@@ -0,0 +1,30 @@
+# -*- coding: utf-8 -*-
+{
+ 'name': "Inbox Notification Email",
+ 'summary': "Send both Odoo notification and email notification",
+ 'description': """
+ This module adds one more option to send notifications via both
+ Odoo's in-app notifications and email.
+ """,
+ 'author': "Odoozone",
+ 'website': "http://odoozone.com/",
+ 'category': "Discuss",
+ 'version': "18.0.1.0.0", # updated for Odoo 18
+ 'depends': ["mail"],
+ 'license': "LGPL-3",
+ 'data': [
+ # "security/ir.model.access.csv",
+ "views/views.xml",
+ "views/templates.xml",
+ ],
+ 'demo': [
+ "demo/demo.xml",
+ ],
+ 'images': [
+ "static/description/banner.PNG",
+ "static/description/icon.png",
+ "static/description/image1.png",
+ ],
+ 'installable': True,
+ 'application': False,
+}
diff --git a/inbox_notif_email/controllers/__init__.py b/inbox_notif_email/controllers/__init__.py
new file mode 100644
index 0000000..457bae2
--- /dev/null
+++ b/inbox_notif_email/controllers/__init__.py
@@ -0,0 +1,3 @@
+# -*- coding: utf-8 -*-
+
+from . import controllers
\ No newline at end of file
diff --git a/inbox_notif_email/controllers/controllers.py b/inbox_notif_email/controllers/controllers.py
new file mode 100644
index 0000000..5bae6c9
--- /dev/null
+++ b/inbox_notif_email/controllers/controllers.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+# from odoo import http
+
+
+# class InboxNotifEmail(http.Controller):
+# @http.route('/inbox_notif_email/inbox_notif_email/', auth='public')
+# def index(self, **kw):
+# return "Hello, world"
+
+# @http.route('/inbox_notif_email/inbox_notif_email/objects/', auth='public')
+# def list(self, **kw):
+# return http.request.render('inbox_notif_email.listing', {
+# 'root': '/inbox_notif_email/inbox_notif_email',
+# 'objects': http.request.env['inbox_notif_email.inbox_notif_email'].search([]),
+# })
+
+# @http.route('/inbox_notif_email/inbox_notif_email/objects//', auth='public')
+# def object(self, obj, **kw):
+# return http.request.render('inbox_notif_email.object', {
+# 'object': obj
+# })
diff --git a/inbox_notif_email/demo/demo.xml b/inbox_notif_email/demo/demo.xml
new file mode 100644
index 0000000..bad20ac
--- /dev/null
+++ b/inbox_notif_email/demo/demo.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/inbox_notif_email/models/__init__.py b/inbox_notif_email/models/__init__.py
new file mode 100644
index 0000000..5305644
--- /dev/null
+++ b/inbox_notif_email/models/__init__.py
@@ -0,0 +1,3 @@
+# -*- coding: utf-8 -*-
+
+from . import models
\ No newline at end of file
diff --git a/inbox_notif_email/models/models.py b/inbox_notif_email/models/models.py
new file mode 100644
index 0000000..64c7f27
--- /dev/null
+++ b/inbox_notif_email/models/models.py
@@ -0,0 +1,2933 @@
+# -*- coding: utf-8 -*-
+
+# from odoo import models, fields, api
+
+
+# class inbox_notif_email(models.Model):
+# _name = 'inbox_notif_email.inbox_notif_email'
+# _description = 'inbox_notif_email.inbox_notif_email'
+
+# name = fields.Char()
+# value = fields.Integer()
+# value2 = fields.Float(compute="_value_pc", store=True)
+# description = fields.Text()
+#
+# @api.depends('value')
+# def _value_pc(self):
+# for record in self:
+# record.value2 = float(record.value) / 100
+import ast
+import base64
+import datetime
+import inspect
+
+import dateutil
+import email
+import email.policy
+import hashlib
+import hmac
+import lxml
+import logging
+import pytz
+import re
+import socket
+import time
+import threading
+
+from collections import namedtuple
+from email.message import EmailMessage
+from email import message_from_string, policy
+from lxml import etree
+from werkzeug import urls
+from xmlrpc import client as xmlrpclib
+
+from odoo import _, api, exceptions, fields, models, tools, registry, SUPERUSER_ID
+from odoo.exceptions import MissingError
+from odoo.osv import expression
+
+from odoo.tools import ustr
+from odoo.tools.misc import clean_context, split_every
+
+_logger = logging.getLogger(__name__)
+
+
+class Users(models.Model):
+ _name = 'res.users'
+ _inherit = ['res.users']
+ notification_type = fields.Selection([
+ ('email', 'Handle by Emails'),
+ ('inbox', 'Handle in Odoo'),
+ ('both', 'Handle by both')
+ ],
+ 'Notification', required=True, default='email',
+ help="Policy on how to handle Chatter notifications:\n"
+ "- Handle by Emails: notifications are sent to your email address\n"
+ "- Handle in Odoo: notifications appear in your Odoo Inbox")
+
+
+class MailNotification(models.Model):
+ _inherit = 'mail.notification'
+ notification_type = fields.Selection([
+ ('inbox', 'Inbox'), ('email', 'Email'),('both', 'both')
+ ], string='Notification Type', default='inbox', index=True, required=True)
+ # _sql_constraints = [
+ # # email notification;: partner is required
+ # ('notification_partner_required',
+ # "CHECK(notification_type NOT IN ('email', 'inbox','both') OR res_partner_id IS NOT NULL)",
+ # 'Customer is required for inbox / email notification'),
+ # ]
+
+
+class MailThread(models.AbstractModel):
+ ''' mail_thread model is meant to be inherited by any model that needs to
+ act as a discussion topic on which messages can be attached. Public
+ methods are prefixed with ``message_`` in order to avoid name
+ collisions with methods of the models that will inherit from this class.
+
+ ``mail.thread`` defines fields used to handle and display the
+ communication history. ``mail.thread`` also manages followers of
+ inheriting classes. All features and expected behavior are managed
+ by mail.thread. Widgets has been designed for the 7.0 and following
+ versions of Odoo.
+
+ Inheriting classes are not required to implement any method, as the
+ default implementation will work for any model. However it is common
+ to override at least the ``message_new`` and ``message_update``
+ methods (calling ``super``) to add model-specific behavior at
+ creation and update of a thread when processing incoming emails.
+
+ Options:
+ - _mail_flat_thread: if set to True, all messages without parent_id
+ are automatically attached to the first message posted on the
+ ressource. If set to False, the display of Chatter is done using
+ threads, and no parent_id is automatically set.
+
+ MailThread features can be somewhat controlled through context keys :
+
+ - ``mail_create_nosubscribe``: at create or message_post, do not subscribe
+ uid to the record thread
+ - ``mail_create_nolog``: at create, do not log the automatic '
+ created' message
+ - ``mail_notrack``: at create and write, do not perform the value tracking
+ creating messages
+ - ``tracking_disable``: at create and write, perform no MailThread features
+ (auto subscription, tracking, post, ...)
+ - ``mail_notify_force_send``: if less than 50 email notifications to send,
+ send them directly instead of using the queue; True by default
+ '''
+ _inherit = 'mail.thread'
+ _description = 'Email Thread'
+ _mail_flat_thread = True # flatten the discussino history
+ _mail_post_access = 'write' # access required on the document to post on it
+ _Attachment = namedtuple('Attachment', ('fname', 'content', 'info'))
+
+ message_is_follower = fields.Boolean(
+ 'Is Follower', compute='_compute_is_follower', search='_search_is_follower')
+ message_follower_ids = fields.One2many(
+ 'mail.followers', 'res_id', string='Followers', groups='base.group_user')
+ message_partner_ids = fields.Many2many(
+ comodel_name='res.partner', string='Followers (Partners)',
+ compute='_get_followers', search='_search_follower_partners',
+ groups='base.group_user')
+ message_channel_ids = fields.Many2many(
+ comodel_name='mail.channel', string='Followers (Channels)',
+ compute='_get_followers', search='_search_follower_channels',
+ groups='base.group_user')
+ message_ids = fields.One2many(
+ 'mail.message', 'res_id', string='Messages',
+ domain=lambda self: [('message_type', '!=', 'user_notification')], auto_join=True)
+ message_unread = fields.Boolean(
+ 'Unread Messages', compute='_get_message_unread',
+ help="If checked, new messages require your attention.")
+ message_unread_counter = fields.Integer(
+ 'Unread Messages Counter', compute='_get_message_unread',
+ help="Number of unread messages")
+ message_needaction = fields.Boolean(
+ 'Action Needed', compute='_get_message_needaction', search='_search_message_needaction',
+ help="If checked, new messages require your attention.")
+ message_needaction_counter = fields.Integer(
+ 'Number of Actions', compute='_get_message_needaction',
+ help="Number of messages which requires an action")
+ message_has_error = fields.Boolean(
+ 'Message Delivery error', compute='_compute_message_has_error', search='_search_message_has_error',
+ help="If checked, some messages have a delivery error.")
+ message_has_error_counter = fields.Integer(
+ 'Number of errors', compute='_compute_message_has_error',
+ help="Number of messages with delivery error")
+ message_attachment_count = fields.Integer('Attachment Count', compute='_compute_message_attachment_count', groups="base.group_user")
+ message_main_attachment_id = fields.Many2one(string="Main Attachment", comodel_name='ir.attachment', index=True, copy=False)
+
+ @api.depends('message_follower_ids')
+ def _get_followers(self):
+ for thread in self:
+ thread.message_partner_ids = thread.message_follower_ids.mapped('partner_id')
+ thread.message_channel_ids = thread.message_follower_ids.mapped('channel_id')
+
+ @api.model
+ def _search_follower_partners(self, operator, operand):
+ """Search function for message_follower_ids
+
+ Do not use with operator 'not in'. Use instead message_is_followers
+ """
+ # TOFIX make it work with not in
+ assert operator != "not in", "Do not search message_follower_ids with 'not in'"
+ followers = self.env['mail.followers'].sudo().search([
+ ('res_model', '=', self._name),
+ ('partner_id', operator, operand)])
+ # using read() below is much faster than followers.mapped('res_id')
+ return [('id', 'in', [res['res_id'] for res in followers.read(['res_id'])])]
+
+ @api.model
+ def _search_follower_channels(self, operator, operand):
+ """Search function for message_follower_ids
+
+ Do not use with operator 'not in'. Use instead message_is_followers
+ """
+ # TOFIX make it work with not in
+ assert operator != "not in", "Do not search message_follower_ids with 'not in'"
+ followers = self.env['mail.followers'].sudo().search([
+ ('res_model', '=', self._name),
+ ('channel_id', operator, operand)])
+ # using read() below is much faster than followers.mapped('res_id')
+ return [('id', 'in', [res['res_id'] for res in followers.read(['res_id'])])]
+
+ @api.depends('message_follower_ids')
+ def _compute_is_follower(self):
+ followers = self.env['mail.followers'].sudo().search([
+ ('res_model', '=', self._name),
+ ('res_id', 'in', self.ids),
+ ('partner_id', '=', self.env.user.partner_id.id),
+ ])
+ print(followers);
+ # using read() below is much faster than followers.mapped('res_id')
+ following_ids = [res['res_id'] for res in followers.read(['res_id'])]
+ for record in self:
+ record.message_is_follower = record.id in following_ids
+
+ @api.model
+ def _search_is_follower(self, operator, operand):
+ followers = self.env['mail.followers'].sudo().search([
+ ('res_model', '=', self._name),
+ ('partner_id', '=', self.env.user.partner_id.id),
+ ])
+ # Cases ('message_is_follower', '=', True) or ('message_is_follower', '!=', False)
+ if (operator == '=' and operand) or (operator == '!=' and not operand):
+ # using read() below is much faster than followers.mapped('res_id')
+ return [('id', 'in', [res['res_id'] for res in followers.read(['res_id'])])]
+ else:
+ # using read() below is much faster than followers.mapped('res_id')
+ return [('id', 'not in', [res['res_id'] for res in followers.read(['res_id'])])]
+
+ def _get_message_unread(self):
+ partner_id = self.env.user.partner_id.id
+ res = dict.fromkeys(self.ids, 0)
+ if self.ids:
+ # search for unread messages, directly in SQL to improve performances
+ self._cr.execute(""" SELECT msg.res_id FROM mail_message msg
+ RIGHT JOIN mail_message_mail_channel_rel rel
+ ON rel.mail_message_id = msg.id
+ RIGHT JOIN mail_channel_partner cp
+ ON (cp.channel_id = rel.mail_channel_id AND cp.partner_id = %s AND
+ (cp.seen_message_id IS NULL OR cp.seen_message_id < msg.id))
+ WHERE msg.model = %s AND msg.res_id = ANY(%s) AND
+ msg.message_type != 'user_notification' AND
+ (msg.author_id IS NULL OR msg.author_id != %s) AND
+ (msg.message_type not in ('notification', 'user_notification') OR msg.model != 'mail.channel')""",
+ (partner_id, self._name, list(self.ids), partner_id,))
+ for result in self._cr.fetchall():
+ res[result[0]] += 1
+
+ for record in self:
+ record.message_unread_counter = res.get(record._origin.id, 0)
+ record.message_unread = bool(record.message_unread_counter)
+
+ def _get_message_needaction(self):
+ res = dict.fromkeys(self.ids, 0)
+ if self.ids:
+ # search for unread messages, directly in SQL to improve performances
+ self._cr.execute(""" SELECT msg.res_id FROM mail_message msg
+ RIGHT JOIN mail_message_res_partner_needaction_rel rel
+ ON rel.mail_message_id = msg.id AND rel.res_partner_id = %s AND (rel.is_read = false OR rel.is_read IS NULL)
+ WHERE msg.model = %s AND msg.res_id in %s AND msg.message_type != 'user_notification'""",
+ (self.env.user.partner_id.id, self._name, tuple(self.ids),))
+ for result in self._cr.fetchall():
+ res[result[0]] += 1
+
+ for record in self:
+ record.message_needaction_counter = res.get(record._origin.id, 0)
+ record.message_needaction = bool(record.message_needaction_counter)
+
+ @api.model
+ def _search_message_needaction(self, operator, operand):
+ return [('message_ids.needaction', operator, operand)]
+
+ def _compute_message_has_error(self):
+ res = {}
+ if self.ids:
+ self._cr.execute(""" SELECT msg.res_id, COUNT(msg.res_id) FROM mail_message msg
+ RIGHT JOIN mail_message_res_partner_needaction_rel rel
+ ON rel.mail_message_id = msg.id AND rel.notification_status in ('exception','bounce')
+ WHERE msg.author_id = %s AND msg.model = %s AND msg.res_id in %s AND msg.message_type != 'user_notification'
+ GROUP BY msg.res_id""",
+ (self.env.user.partner_id.id, self._name, tuple(self.ids),))
+ res.update(self._cr.fetchall())
+
+ for record in self:
+ record.message_has_error_counter = res.get(record._origin.id, 0)
+ record.message_has_error = bool(record.message_has_error_counter)
+
+ @api.model
+ def _search_message_has_error(self, operator, operand):
+ message_ids = self.env['mail.message']._search([('has_error', operator, operand), ('author_id', '=', self.env.user.partner_id.id)])
+ return [('message_ids', 'in', message_ids)]
+
+ def _compute_message_attachment_count(self):
+ read_group_var = self.env['ir.attachment'].read_group([('res_id', 'in', self.ids), ('res_model', '=', self._name)],
+ fields=['res_id'],
+ groupby=['res_id'])
+
+ attachment_count_dict = dict((d['res_id'], d['res_id_count']) for d in read_group_var)
+ for record in self:
+ record.message_attachment_count = attachment_count_dict.get(record.id, 0)
+
+ # ------------------------------------------------------------
+ # CRUD
+ # ------------------------------------------------------------
+
+ # @api.model_create_multi
+ # def create(self, vals_list):
+ # """ Chatter override :
+ # - subscribe uid
+ # - subscribe followers of parent
+ # - log a creation message
+ # """
+ # if self._context.get('tracking_disable'):
+ # threads = super(MailThread, self).create(vals_list)
+ # threads._discard_tracking()
+ # return threads
+ # curframe = inspect.currentframe()
+ # calframe = inspect.getouterframes(curframe, 2)
+ # print("vals_list : ", vals_list)
+ # print('caller name:', calframe)
+ #
+ # threads = super(MailThread, self).create(vals_list)
+ #
+ #
+ # # subscribe uid unless asked not to
+ # if not self._context.get('mail_create_nosubscribe'):
+ # for thread in threads:
+ # self.env['mail.followers']._insert_followers(
+ # thread._name, thread.ids, self.env.user.partner_id.ids,
+ # None, None, None,
+ # customer_ids=[],
+ # check_existing=False
+ # )
+ #
+ # # auto_subscribe: take values and defaults into account
+ # create_values_list = {}
+ # for thread, values in zip(threads, vals_list):
+ # create_values = dict(values)
+ # for key, val in self._context.items():
+ # if key.startswith('default_') and key[8:] not in create_values:
+ # create_values[key[8:]] = val
+ # thread._message_auto_subscribe(create_values, followers_existing_policy='update')
+ # create_values_list[thread.id] = create_values
+ #
+ # # automatic logging unless asked not to (mainly for various testing purpose)
+ # if not self._context.get('mail_create_nolog'):
+ # threads_no_subtype = self.env[self._name]
+ # for thread in threads:
+ # subtype = thread._creation_subtype()
+ # if subtype: # if we have a subtype, post message to notify users from _message_auto_subscribe
+ # thread.sudo().message_post(subtype_id=subtype.id, author_id=self.env.user.partner_id.id)
+ # else:
+ # threads_no_subtype += thread
+ # if threads_no_subtype:
+ # bodies = dict(
+ # (thread.id, thread._creation_message())
+ # for thread in threads_no_subtype)
+ # threads_no_subtype._message_log_batch(bodies=bodies)
+ #
+ # # post track template if a tracked field changed
+ # threads._discard_tracking()
+ # if not self._context.get('mail_notrack'):
+ # fnames = self._get_tracked_fields()
+ # for thread in threads:
+ # create_values = create_values_list[thread.id]
+ # changes = [fname for fname in fnames if create_values.get(fname)]
+ # # based on tracked field to stay consistent with write
+ # # we don't consider that a falsy field is a change, to stay consistent with previous implementation,
+ # # but we may want to change that behaviour later.
+ # thread._message_track_post_template(changes)
+ #
+ # return threads
+
+ def write(self, values):
+ if self._context.get('tracking_disable'):
+ return super(MailThread, self).write(values)
+
+ if not self._context.get('mail_notrack'):
+ self._prepare_tracking(self._fields)
+
+ # Perform write
+ result = super(MailThread, self).write(values)
+
+ # update followers
+ self._message_auto_subscribe(values)
+
+ return result
+
+ def unlink(self):
+ """ Override unlink to delete messages and followers. This cannot be
+ cascaded, because link is done through (res_model, res_id). """
+ if not self:
+ return True
+ # discard pending tracking
+ self._discard_tracking()
+ self.env['mail.message'].search([('model', '=', self._name), ('res_id', 'in', self.ids)]).sudo().unlink()
+ res = super(MailThread, self).unlink()
+ self.env['mail.followers'].sudo().search(
+ [('res_model', '=', self._name), ('res_id', 'in', self.ids)]
+ ).unlink()
+ return res
+
+ def copy_data(self, default=None):
+ # avoid tracking multiple temporary changes during copy
+ return super(MailThread, self.with_context(mail_notrack=True)).copy_data(default=default)
+
+ @api.model
+ def get_empty_list_help(self, help):
+ """ Override of BaseModel.get_empty_list_help() to generate an help message
+ that adds alias information. """
+ model = self._context.get('empty_list_help_model')
+ res_id = self._context.get('empty_list_help_id')
+ catchall_domain = self.env['ir.config_parameter'].sudo().get_param("mail.catchall.domain")
+ document_name = self._context.get('empty_list_help_document_name', _('document'))
+ nothing_here = not help
+ alias = None
+
+ if catchall_domain and model and res_id: # specific res_id -> find its alias (i.e. section_id specified)
+ record = self.env[model].sudo().browse(res_id)
+ # check that the alias effectively creates new records
+ if record.alias_id and record.alias_id.alias_name and \
+ record.alias_id.alias_model_id and \
+ record.alias_id.alias_model_id.model == self._name and \
+ record.alias_id.alias_force_thread_id == 0:
+ alias = record.alias_id
+ if not alias and catchall_domain and model: # no res_id or res_id not linked to an alias -> generic help message, take a generic alias of the model
+ Alias = self.env['mail.alias']
+ aliases = Alias.search([
+ ("alias_parent_model_id.model", "=", model),
+ ("alias_name", "!=", False),
+ ('alias_force_thread_id', '=', False),
+ ('alias_parent_thread_id', '=', False)], order='id ASC')
+ if aliases and len(aliases) == 1:
+ alias = aliases[0]
+
+ if alias:
+ email_link = "%(email)s " % {'email': alias.display_name}
+ if nothing_here:
+ return "%(dyn_help)s
" % {
+ 'dyn_help': _("Add a new %(document)s or send an email to %(email_link)s",
+ document=document_name,
+ email_link=email_link,
+ )
+ }
+ # do not add alias two times if it was added previously
+ if "oe_view_nocontent_alias" not in help:
+ return "%(static_help)s%(dyn_help)s
" % {
+ 'static_help': help,
+ 'dyn_help': _("Create new %(document)s by sending an email to %(email_link)s",
+ document=document_name,
+ email_link=email_link,
+ )
+ }
+
+ if nothing_here:
+ return "%(dyn_help)s
" % {
+ 'dyn_help': _("Create new %(document)s", document=document_name),
+ }
+
+ return help
+
+ # ------------------------------------------------------
+ # MODELS / CRUD HELPERS
+ # ------------------------------------------------------
+
+ def _compute_field_value(self, field):
+ if not self._context.get('tracking_disable') and not self._context.get('mail_notrack'):
+ self._prepare_tracking(f.name for f in self.pool.field_computed[field] if f.store)
+
+ return super()._compute_field_value(field)
+
+ def _creation_subtype(self):
+ """ Give the subtypes triggered by the creation of a record
+
+ :returns: a subtype browse record (empty if no subtype is triggered)
+ """
+ return self.env['mail.message.subtype']
+
+ def _get_creation_message(self):
+ """ Deprecated, remove in 14+ """
+ return self._creation_message()
+
+ def _creation_message(self):
+ """ Get the creation message to log into the chatter at the record's creation.
+ :returns: The message's body to log.
+ """
+ self.ensure_one()
+ doc_name = self.env['ir.model']._get(self._name).name
+ return _('%s created', doc_name)
+
+ @api.model
+ def get_mail_message_access(self, res_ids, operation, model_name=None):
+ """ Deprecated, remove with v14+ """
+ return self._get_mail_message_access(res_ids, operation, model_name=model_name)
+
+ @api.model
+ def _get_mail_message_access(self, res_ids, operation, model_name=None):
+ """ mail.message check permission rules for related document. This method is
+ meant to be inherited in order to implement addons-specific behavior.
+ A common behavior would be to allow creating messages when having read
+ access rule on the document, for portal document such as issues. """
+
+ DocModel = self.env[model_name] if model_name else self
+ create_allow = getattr(DocModel, '_mail_post_access', 'write')
+
+ if operation in ['write', 'unlink']:
+ check_operation = 'write'
+ elif operation == 'create' and create_allow in ['create', 'read', 'write', 'unlink']:
+ check_operation = create_allow
+ elif operation == 'create':
+ check_operation = 'write'
+ else:
+ check_operation = operation
+ return check_operation
+
+ def _valid_field_parameter(self, field, name):
+ # allow tracking on models inheriting from 'mail.thread'
+ return name == 'tracking' or super()._valid_field_parameter(field, name)
+
+ def with_lang(self):
+ """ Deprecated, remove in 14+ """
+ return self._fallback_lang()
+
+ def _fallback_lang(self):
+ if not self._context.get("lang"):
+ return self.with_context(lang=self.env.user.lang)
+ return self
+
+ # ------------------------------------------------------
+ # WRAPPERS AND TOOLS
+ # ------------------------------------------------------
+
+ def message_change_thread(self, new_thread):
+ """
+ Transfer the list of the mail thread messages from an model to another
+
+ :param id : the old res_id of the mail.message
+ :param new_res_id : the new res_id of the mail.message
+ :param new_model : the name of the new model of the mail.message
+
+ Example : my_lead.message_change_thread(my_project_task)
+ will transfer the context of the thread of my_lead to my_project_task
+ """
+ self.ensure_one()
+ # get the subtype of the comment Message
+ subtype_comment = self.env['ir.model.data'].xmlid_to_res_id('mail.mt_comment')
+
+ # get the ids of the comment and not-comment of the thread
+ # TDE check: sudo on mail.message, to be sure all messages are moved ?
+ MailMessage = self.env['mail.message']
+ msg_comment = MailMessage.search([
+ ('model', '=', self._name),
+ ('res_id', '=', self.id),
+ ('message_type', '!=', 'user_notification'),
+ ('subtype_id', '=', subtype_comment)])
+ msg_not_comment = MailMessage.search([
+ ('model', '=', self._name),
+ ('res_id', '=', self.id),
+ ('message_type', '!=', 'user_notification'),
+ ('subtype_id', '!=', subtype_comment)])
+
+ # update the messages
+ msg_comment.write({"res_id": new_thread.id, "model": new_thread._name})
+ msg_not_comment.write({"res_id": new_thread.id, "model": new_thread._name, "subtype_id": None})
+ return True
+
+ # ------------------------------------------------------
+ # TRACKING / LOG
+ # ------------------------------------------------------
+
+ def _prepare_tracking(self, fields):
+ """ Prepare the tracking of ``fields`` for ``self``.
+
+ :param fields: iterable of fields names to potentially track
+ """
+ fnames = self._get_tracked_fields().intersection(fields)
+ if not fnames:
+ return
+ self.env.cr.precommit.add(self._finalize_tracking)
+ initial_values = self.env.cr.precommit.data.setdefault(f'mail.tracking.{self._name}', {})
+ for record in self:
+ if not record.id:
+ continue
+ values = initial_values.setdefault(record.id, {})
+ if values is not None:
+ for fname in fnames:
+ values.setdefault(fname, record[fname])
+
+ def _discard_tracking(self):
+ """ Prevent any tracking of fields on ``self``. """
+ if not self._get_tracked_fields():
+ return
+ self.env.cr.precommit.add(self._finalize_tracking)
+ initial_values = self.env.cr.precommit.data.setdefault(f'mail.tracking.{self._name}', {})
+ # disable tracking by setting initial values to None
+ for id_ in self.ids:
+ initial_values[id_] = None
+
+ def _finalize_tracking(self):
+ """ Generate the tracking messages for the records that have been
+ prepared with ``_prepare_tracking``.
+ """
+ initial_values = self.env.cr.precommit.data.pop(f'mail.tracking.{self._name}', {})
+ ids = [id_ for id_, vals in initial_values.items() if vals]
+ if not ids:
+ return
+ records = self.browse(ids).sudo()
+ fnames = self._get_tracked_fields()
+ context = clean_context(self._context)
+ tracking = records.with_context(context).message_track(fnames, initial_values)
+ for record in records:
+ changes, tracking_value_ids = tracking.get(record.id, (None, None))
+ record._message_track_post_template(changes)
+ # this method is called after the main flush() and just before commit();
+ # we have to flush() again in case we triggered some recomputations
+ self.flush()
+
+ @tools.ormcache('self.env.uid', 'self.env.su')
+ def _get_tracked_fields(self):
+ """ Return the set of tracked fields names for the current model. """
+ fields = {
+ name
+ for name, field in self._fields.items()
+ if getattr(field, 'tracking', None) or getattr(field, 'track_visibility', None)
+ }
+
+ return fields and set(self.fields_get(fields))
+
+ def _message_track_post_template(self, changes):
+ if not changes:
+ return True
+ # Clean the context to get rid of residual default_* keys
+ # that could cause issues afterward during the mail.message
+ # generation. Example: 'default_parent_id' would refer to
+ # the parent_id of the current record that was used during
+ # its creation, but could refer to wrong parent message id,
+ # leading to a traceback in case the related message_id
+ # doesn't exist
+ self = self.with_context(clean_context(self._context))
+ templates = self._track_template(changes)
+ for field_name, (template, post_kwargs) in templates.items():
+ if not template:
+ continue
+ if isinstance(template, str):
+ self._fallback_lang().message_post_with_view(template, **post_kwargs)
+ else:
+ self._fallback_lang().message_post_with_template(template.id, **post_kwargs)
+ return True
+
+ def _track_template(self, changes):
+ return dict()
+
+ def message_track(self, tracked_fields, initial_values):
+ """ Track updated values. Comparing the initial and current values of
+ the fields given in tracked_fields, it generates a message containing
+ the updated values. This message can be linked to a mail.message.subtype
+ given by the ``_track_subtype`` method.
+
+ :param tracked_fields: iterable of field names to track
+ :param initial_values: mapping {record_id: {field_name: value}}
+ :return: mapping {record_id: (changed_field_names, tracking_value_ids)}
+ containing existing records only
+ """
+ if not tracked_fields:
+ return True
+
+ tracked_fields = self.fields_get(tracked_fields)
+ tracking = dict()
+ for record in self:
+ try:
+ tracking[record.id] = record._message_track(tracked_fields, initial_values[record.id])
+ except MissingError:
+ continue
+
+ for record in self:
+ changes, tracking_value_ids = tracking.get(record.id, (None, None))
+ if not changes:
+ continue
+
+ # find subtypes and post messages or log if no subtype found
+ subtype = False
+ # By passing this key, that allows to let the subtype empty and so don't sent email because partners_to_notify from mail_message._notify will be empty
+ if not self._context.get('mail_track_log_only'):
+ subtype = record._track_subtype(dict((col_name, initial_values[record.id][col_name]) for col_name in changes))
+ if subtype:
+ if not subtype.exists():
+ _logger.debug('subtype "%s" not found' % subtype.name)
+ continue
+ record.message_post(subtype_id=subtype.id, tracking_value_ids=tracking_value_ids)
+ elif tracking_value_ids:
+ record._message_log(tracking_value_ids=tracking_value_ids)
+
+ return tracking
+
+ def static_message_track(self, record, tracked_fields, initial):
+ """ Deprecated, remove in v14+ """
+ return record._mail_track(tracked_fields, initial)
+
+ def _message_track(self, tracked_fields, initial):
+ """ Moved to ``BaseModel._mail_track()`` """
+ return self._mail_track(tracked_fields, initial)
+
+ def _track_subtype(self, init_values):
+ """ Give the subtypes triggered by the changes on the record according
+ to values that have been updated.
+
+ :param init_values: the original values of the record; only modified fields
+ are present in the dict
+ :type init_values: dict
+ :returns: a subtype browse record or False if no subtype is trigerred
+ """
+ return False
+
+ # ------------------------------------------------------
+ # MAIL GATEWAY
+ # ------------------------------------------------------
+
+ def _routing_warn(self, error_message, message_id, route, raise_exception=True):
+ """ Tools method used in _routing_check_route: whether to log a warning or raise an error """
+ short_message = _("Mailbox unavailable - %s", error_message)
+ full_message = ('Routing mail with Message-Id %s: route %s: %s' %
+ (message_id, route, error_message))
+ _logger.info(full_message)
+ if raise_exception:
+ # sender should not see private diagnostics info, just the error
+ raise ValueError(short_message)
+
+ def _routing_create_bounce_email(self, email_from, body_html, message, **mail_values):
+ bounce_to = tools.decode_message_header(message, 'Return-Path') or email_from
+ bounce_mail_values = {
+ 'author_id': False,
+ 'body_html': body_html,
+ 'subject': 'Re: %s' % message.get('subject'),
+ 'email_to': bounce_to,
+ 'auto_delete': True,
+ }
+ bounce_from = self.env['ir.mail_server']._get_default_bounce_address()
+ if bounce_from:
+ bounce_mail_values['email_from'] = tools.formataddr(('MAILER-DAEMON', bounce_from))
+ elif self.env['ir.config_parameter'].sudo().get_param("mail.catchall.alias") not in message['To']:
+ bounce_mail_values['email_from'] = tools.decode_message_header(message, 'To')
+ else:
+ bounce_mail_values['email_from'] = tools.formataddr(('MAILER-DAEMON', self.env.user.email_normalized))
+ bounce_mail_values.update(mail_values)
+ self.env['mail.mail'].sudo().create(bounce_mail_values).send()
+
+ @api.model
+ def _routing_handle_bounce(self, email_message, message_dict):
+ """ Handle bounce of incoming email. Based on values of the bounce (email
+ and related partner, send message and its messageID)
+
+ * find blacklist-enabled records with email_normalized = bounced email
+ and call ``_message_receive_bounce`` on each of them to propagate
+ bounce information through various records linked to same email;
+ * if not already done (i.e. if original record is not blacklist enabled
+ like a bounce on an applicant), find record linked to bounced message
+ and call ``_message_receive_bounce``;
+
+ :param email_message: incoming email;
+ :type email_message: email.message;
+ :param message_dict: dictionary holding already-parsed values and in
+ which bounce-related values will be added;
+ :type message_dict: dictionary;
+ """
+ bounced_record, bounced_record_done = False, False
+ bounced_email, bounced_partner = message_dict['bounced_email'], message_dict['bounced_partner']
+ bounced_msg_id, bounced_message = message_dict['bounced_msg_id'], message_dict['bounced_message']
+
+ if bounced_email:
+ bounced_model, bounced_res_id = bounced_message.model, bounced_message.res_id
+
+ if bounced_model and bounced_model in self.env and bounced_res_id:
+ bounced_record = self.env[bounced_model].sudo().browse(bounced_res_id).exists()
+
+ bl_models = self.env['ir.model'].sudo().search(['&', ('is_mail_blacklist', '=', True), ('model', '!=', 'mail.thread.blacklist')])
+ for model in [bl_model for bl_model in bl_models if bl_model.model in self.env]: # transient test mode
+ rec_bounce_w_email = self.env[model.model].sudo().search([('email_normalized', '=', bounced_email)])
+ rec_bounce_w_email._message_receive_bounce(bounced_email, bounced_partner)
+ bounced_record_done = bool(bounced_record and model.model == bounced_model and bounced_record in rec_bounce_w_email)
+
+ # set record as bounced unless already done due to blacklist mixin
+ if bounced_record and not bounced_record_done and issubclass(type(bounced_record), self.pool['mail.thread']):
+ bounced_record._message_receive_bounce(bounced_email, bounced_partner)
+
+ if bounced_partner and bounced_message:
+ self.env['mail.notification'].sudo().search([
+ ('mail_message_id', '=', bounced_message.id),
+ ('res_partner_id', 'in', bounced_partner.ids)]
+ ).write({'notification_status': 'bounce'})
+
+ if bounced_record:
+ _logger.info('Routing mail from %s to %s with Message-Id %s: not routing bounce email from %s replying to %s (model %s ID %s)',
+ message_dict['email_from'], message_dict['to'], message_dict['message_id'], bounced_email, bounced_msg_id, bounced_model, bounced_res_id)
+ elif bounced_email:
+ _logger.info('Routing mail from %s to %s with Message-Id %s: not routing bounce email from %s replying to %s (no document found)',
+ message_dict['email_from'], message_dict['to'], message_dict['message_id'], bounced_email, bounced_msg_id)
+ else:
+ _logger.info('Routing mail from %s to %s with Message-Id %s: not routing bounce email.',
+ message_dict['email_from'], message_dict['to'], message_dict['message_id'])
+
+ @api.model
+ def _routing_check_route(self, message, message_dict, route, raise_exception=True):
+ """ Verify route validity. Check and rules:
+ 1 - if thread_id -> check that document effectively exists; otherwise
+ fallback on a message_new by resetting thread_id
+ 2 - check that message_update exists if thread_id is set; or at least
+ that message_new exist
+ 3 - if there is an alias, check alias_contact:
+ 'followers' and thread_id:
+ check on target document that the author is in the followers
+ 'followers' and alias_parent_thread_id:
+ check on alias parent document that the author is in the
+ followers
+ 'partners': check that author_id id set
+
+ :param message: an email.message instance
+ :param message_dict: dictionary of values that will be given to
+ mail_message.create()
+ :param route: route to check which is a tuple (model, thread_id,
+ custom_values, uid, alias)
+ :param raise_exception: if an error occurs, tell whether to raise an error
+ or just log a warning and try other processing or
+ invalidate route
+ """
+
+ assert isinstance(route, (list, tuple)), 'A route should be a list or a tuple'
+ assert len(route) == 5, 'A route should contain 5 elements: model, thread_id, custom_values, uid, alias record'
+
+ message_id = message_dict['message_id']
+ email_from = message_dict['email_from']
+ author_id = message_dict.get('author_id')
+ model, thread_id, alias = route[0], route[1], route[4]
+ record_set = None
+
+ # Wrong model
+ if not model:
+ self._routing_warn(_('target model unspecified'), message_id, route, raise_exception)
+ return ()
+ elif model not in self.env:
+ self._routing_warn(_('unknown target model %s', model), message_id, route, raise_exception)
+ return ()
+ record_set = self.env[model].browse(thread_id) if thread_id else self.env[model]
+
+ # Existing Document: check if exists and model accepts the mailgateway; if not, fallback on create if allowed
+ if thread_id:
+ if not record_set.exists():
+ self._routing_warn(
+ _('reply to missing document (%(model)s,%(thread)s), fall back on document creation', model=model, thread=thread_id),
+ message_id,
+ route,
+ False
+ )
+ thread_id = None
+ elif not hasattr(record_set, 'message_update'):
+ self._routing_warn(_('reply to model %s that does not accept document update, fall back on document creation', model), message_id, route, False)
+ thread_id = None
+
+ # New Document: check model accepts the mailgateway
+ if not thread_id and model and not hasattr(record_set, 'message_new'):
+ self._routing_warn(_('model %s does not accept document creation', model), message_id, route, raise_exception)
+ return ()
+
+ # Update message author. We do it now because we need it for aliases (contact settings)
+ if not author_id:
+ if record_set:
+ authors = self._mail_find_partner_from_emails([email_from], records=record_set)
+ elif alias and alias.alias_parent_model_id and alias.alias_parent_thread_id:
+ records = self.env[alias.alias_parent_model_id.model].browse(alias.alias_parent_thread_id)
+ authors = self._mail_find_partner_from_emails([email_from], records=records)
+ else:
+ authors = self._mail_find_partner_from_emails([email_from], records=None)
+ if authors:
+ message_dict['author_id'] = authors[0].id
+
+ # Alias: check alias_contact settings
+ if alias:
+ if thread_id:
+ obj = record_set[0]
+ elif alias.alias_parent_model_id and alias.alias_parent_thread_id:
+ obj = self.env[alias.alias_parent_model_id.model].browse(alias.alias_parent_thread_id)
+ else:
+ obj = self.env[model]
+ error_message = obj._alias_get_error_message(message, message_dict, alias)
+ if error_message:
+ self._routing_warn(
+ _('alias %(name)s: %(error)s', name=alias.alias_name, error=error_message or _('unknown error')),
+ message_id,
+ route,
+ False
+ )
+ body = alias._get_alias_bounced_body(message_dict)
+ self._routing_create_bounce_email(email_from, body, message, references=message_id)
+ return False
+
+ return (model, thread_id, route[2], route[3], route[4])
+
+ @api.model
+ def _routing_reset_bounce(self, email_message, message_dict):
+ """Called by ``message_process`` when a new mail is received from an email address.
+ If the email is related to a partner, we consider that the number of message_bounce
+ is not relevant anymore as the email is valid - as we received an email from this
+ address. The model is here hardcoded because we cannot know with which model the
+ incomming mail match. We consider that if a mail arrives, we have to clear bounce for
+ each model having bounce count.
+
+ :param email_from: email address that sent the incoming email."""
+ valid_email = message_dict['email_from']
+ if valid_email:
+ bl_models = self.env['ir.model'].sudo().search(['&', ('is_mail_blacklist', '=', True), ('model', '!=', 'mail.thread.blacklist')])
+ for model in [bl_model for bl_model in bl_models if bl_model.model in self.env]: # transient test mode
+ self.env[model.model].sudo().search([('message_bounce', '>', 0), ('email_normalized', '=', valid_email)])._message_reset_bounce(valid_email)
+
+ @api.model
+ def message_route(self, message, message_dict, model=None, thread_id=None, custom_values=None):
+ """ Attempt to figure out the correct target model, thread_id,
+ custom_values and user_id to use for an incoming message.
+ Multiple values may be returned, if a message had multiple
+ recipients matching existing mail.aliases, for example.
+
+ The following heuristics are used, in this order:
+
+ * if the message replies to an existing thread by having a Message-Id
+ that matches an existing mail_message.message_id, we take the original
+ message model/thread_id pair and ignore custom_value as no creation will
+ take place;
+ * look for a mail.alias entry matching the message recipients and use the
+ corresponding model, thread_id, custom_values and user_id. This could
+ lead to a thread update or creation depending on the alias;
+ * fallback on provided ``model``, ``thread_id`` and ``custom_values``;
+ * raise an exception as no route has been found
+
+ :param string message: an email.message instance
+ :param dict message_dict: dictionary holding parsed message variables
+ :param string model: the fallback model to use if the message does not match
+ any of the currently configured mail aliases (may be None if a matching
+ alias is supposed to be present)
+ :type dict custom_values: optional dictionary of default field values
+ to pass to ``message_new`` if a new record needs to be created.
+ Ignored if the thread record already exists, and also if a matching
+ mail.alias was found (aliases define their own defaults)
+ :param int thread_id: optional ID of the record/thread from ``model`` to
+ which this mail should be attached. Only used if the message does not
+ reply to an existing thread and does not match any mail alias.
+ :return: list of routes [(model, thread_id, custom_values, user_id, alias)]
+
+ :raises: ValueError, TypeError
+ """
+ if not isinstance(message, EmailMessage):
+ raise TypeError('message must be an email.message.EmailMessage at this point')
+ catchall_alias = self.env['ir.config_parameter'].sudo().get_param("mail.catchall.alias")
+ bounce_alias = self.env['ir.config_parameter'].sudo().get_param("mail.bounce.alias")
+ fallback_model = model
+
+ # get email.message.Message variables for future processing
+ local_hostname = socket.gethostname()
+ message_id = message_dict['message_id']
+
+ # compute references to find if message is a reply to an existing thread
+ thread_references = message_dict['references'] or message_dict['in_reply_to']
+ msg_references = [
+ re.sub(r'[\r\n\t ]+', r'', ref) # "Unfold" buggy references
+ for ref in tools.mail_header_msgid_re.findall(thread_references)
+ if 'reply_to' not in ref
+ ]
+ mail_messages = self.env['mail.message'].sudo().search([('message_id', 'in', msg_references)], limit=1, order='id desc, message_id')
+ is_a_reply = bool(mail_messages)
+ reply_model, reply_thread_id = mail_messages.model, mail_messages.res_id
+
+ # author and recipients
+ email_from = message_dict['email_from']
+ email_from_localpart = (tools.email_split(email_from) or [''])[0].split('@', 1)[0].lower()
+ email_to = message_dict['to']
+ email_to_localparts = [
+ e.split('@', 1)[0].lower()
+ for e in (tools.email_split(email_to) or [''])
+ ]
+ # Delivered-To is a safe bet in most modern MTAs, but we have to fallback on To + Cc values
+ # for all the odd MTAs out there, as there is no standard header for the envelope's `rcpt_to` value.
+ rcpt_tos_localparts = [
+ e.split('@')[0].lower()
+ for e in tools.email_split(message_dict['recipients'])
+ ]
+ rcpt_tos_valid_localparts = [to for to in rcpt_tos_localparts]
+
+ # 0. Handle bounce: verify whether this is a bounced email and use it to collect bounce data and update notifications for customers
+ # Bounce regex: typical form of bounce is bounce_alias+128-crm.lead-34@domain
+ # group(1) = the mail ID; group(2) = the model (if any); group(3) = the record ID
+ # Bounce message (not alias)
+ # See http://datatracker.ietf.org/doc/rfc3462/?include_text=1
+ # As all MTA does not respect this RFC (googlemail is one of them),
+ # we also need to verify if the message come from "mailer-daemon"
+ # If not a bounce: reset bounce information
+ if bounce_alias and any(email.startswith(bounce_alias) for email in email_to_localparts):
+ bounce_re = re.compile("%s\+(\d+)-?([\w.]+)?-?(\d+)?" % re.escape(bounce_alias), re.UNICODE)
+ bounce_match = bounce_re.search(email_to)
+ if bounce_match:
+ self._routing_handle_bounce(message, message_dict)
+ return []
+ if message.get_content_type() == 'multipart/report' or email_from_localpart == 'mailer-daemon':
+ self._routing_handle_bounce(message, message_dict)
+ return []
+ self._routing_reset_bounce(message, message_dict)
+
+ # 1. Handle reply
+ # if destination = alias with different model -> consider it is a forward and not a reply
+ # if destination = alias with same model -> check contact settings as they still apply
+ if reply_model and reply_thread_id:
+ other_model_aliases = self.env['mail.alias'].search([
+ '&', '&',
+ ('alias_name', '!=', False),
+ ('alias_name', 'in', email_to_localparts),
+ ('alias_model_id.model', '!=', reply_model),
+ ])
+ if other_model_aliases:
+ is_a_reply = False
+ rcpt_tos_valid_localparts = [to for to in rcpt_tos_valid_localparts if to in other_model_aliases.mapped('alias_name')]
+
+ if is_a_reply:
+ dest_aliases = self.env['mail.alias'].search([
+ ('alias_name', 'in', rcpt_tos_localparts),
+ ('alias_model_id.model', '=', reply_model)
+ ], limit=1)
+
+ user_id = self._mail_find_user_for_gateway(email_from, alias=dest_aliases).id or self._uid
+ route = self._routing_check_route(
+ message, message_dict,
+ (reply_model, reply_thread_id, custom_values, user_id, dest_aliases),
+ raise_exception=False)
+ if route:
+ _logger.info(
+ 'Routing mail from %s to %s with Message-Id %s: direct reply to msg: model: %s, thread_id: %s, custom_values: %s, uid: %s',
+ email_from, email_to, message_id, reply_model, reply_thread_id, custom_values, self._uid)
+ return [route]
+ elif route is False:
+ return []
+
+ # 2. Handle new incoming email by checking aliases and applying their settings
+ if rcpt_tos_localparts:
+ # no route found for a matching reference (or reply), so parent is invalid
+ message_dict.pop('parent_id', None)
+
+ # check it does not directly contact catchall
+ if catchall_alias and email_to_localparts and all(email_localpart == catchall_alias for email_localpart in email_to_localparts):
+ _logger.info('Routing mail from %s to %s with Message-Id %s: direct write to catchall, bounce', email_from, email_to, message_id)
+ body = self.env.ref('mail.mail_bounce_catchall')._render({
+ 'message': message,
+ }, engine='ir.qweb')
+ self._routing_create_bounce_email(email_from, body, message, references=message_id, reply_to=self.env.company.email)
+ return []
+
+ dest_aliases = self.env['mail.alias'].search([('alias_name', 'in', rcpt_tos_valid_localparts)])
+ if dest_aliases:
+ routes = []
+ for alias in dest_aliases:
+ user_id = self._mail_find_user_for_gateway(email_from, alias=alias).id or self._uid
+ route = (alias.alias_model_id.model, alias.alias_force_thread_id, ast.literal_eval(alias.alias_defaults), user_id, alias)
+ route = self._routing_check_route(message, message_dict, route, raise_exception=True)
+ if route:
+ _logger.info(
+ 'Routing mail from %s to %s with Message-Id %s: direct alias match: %r',
+ email_from, email_to, message_id, route)
+ routes.append(route)
+ return routes
+
+ # 3. Fallback to the provided parameters, if they work
+ if fallback_model:
+ # no route found for a matching reference (or reply), so parent is invalid
+ message_dict.pop('parent_id', None)
+ user_id = self._mail_find_user_for_gateway(email_from).id or self._uid
+ route = self._routing_check_route(
+ message, message_dict,
+ (fallback_model, thread_id, custom_values, user_id, None),
+ raise_exception=True)
+ if route:
+ _logger.info(
+ 'Routing mail from %s to %s with Message-Id %s: fallback to model:%s, thread_id:%s, custom_values:%s, uid:%s',
+ email_from, email_to, message_id, fallback_model, thread_id, custom_values, user_id)
+ return [route]
+
+ # ValueError if no routes found and if no bounce occured
+ raise ValueError(
+ 'No possible route found for incoming message from %s to %s (Message-Id %s:). '
+ 'Create an appropriate mail.alias or force the destination model.' %
+ (email_from, email_to, message_id)
+ )
+
+ @api.model
+ def _message_route_process(self, message, message_dict, routes):
+ self = self.with_context(attachments_mime_plainxml=True) # import XML attachments as text
+ # postpone setting message_dict.partner_ids after message_post, to avoid double notifications
+ original_partner_ids = message_dict.pop('partner_ids', [])
+ thread_id = False
+ for model, thread_id, custom_values, user_id, alias in routes or ():
+ subtype_id = False
+ related_user = self.env['res.users'].browse(user_id)
+ Model = self.env[model].with_context(mail_create_nosubscribe=True, mail_create_nolog=True)
+ if not (thread_id and hasattr(Model, 'message_update') or hasattr(Model, 'message_new')):
+ raise ValueError(
+ "Undeliverable mail with Message-Id %s, model %s does not accept incoming emails" %
+ (message_dict['message_id'], model)
+ )
+
+ # disabled subscriptions during message_new/update to avoid having the system user running the
+ # email gateway become a follower of all inbound messages
+ ModelCtx = Model.with_user(related_user).sudo()
+ if thread_id and hasattr(ModelCtx, 'message_update'):
+ thread = ModelCtx.browse(thread_id)
+ thread.message_update(message_dict)
+ else:
+ # if a new thread is created, parent is irrelevant
+ message_dict.pop('parent_id', None)
+ thread = ModelCtx.message_new(message_dict, custom_values)
+ thread_id = thread.id
+ subtype_id = thread._creation_subtype().id
+
+ # replies to internal message are considered as notes, but parent message
+ # author is added in recipients to ensure he is notified of a private answer
+ parent_message = False
+ if message_dict.get('parent_id'):
+ parent_message = self.env['mail.message'].sudo().browse(message_dict['parent_id'])
+ partner_ids = []
+ if not subtype_id:
+ if message_dict.get('is_internal'):
+ subtype_id = self.env['ir.model.data'].xmlid_to_res_id('mail.mt_note')
+ if parent_message and parent_message.author_id:
+ partner_ids = [parent_message.author_id.id]
+ else:
+ subtype_id = self.env['ir.model.data'].xmlid_to_res_id('mail.mt_comment')
+
+ post_params = dict(subtype_id=subtype_id, partner_ids=partner_ids, **message_dict)
+ # remove computational values not stored on mail.message and avoid warnings when creating it
+ for x in ('from', 'to', 'cc', 'recipients', 'references', 'in_reply_to', 'bounced_email', 'bounced_message', 'bounced_msg_id', 'bounced_partner'):
+ post_params.pop(x, None)
+ new_msg = False
+ if thread._name == 'mail.thread': # message with parent_id not linked to record
+ new_msg = thread.message_notify(**post_params)
+ else:
+ # parsing should find an author independently of user running mail gateway, and ensure it is not odoobot
+ partner_from_found = message_dict.get('author_id') and message_dict['author_id'] != self.env['ir.model.data'].xmlid_to_res_id('base.partner_root')
+ thread = thread.with_context(mail_create_nosubscribe=not partner_from_found)
+ new_msg = thread.message_post(**post_params)
+
+ if new_msg and original_partner_ids:
+ # postponed after message_post, because this is an external message and we don't want to create
+ # duplicate emails due to notifications
+ new_msg.write({'partner_ids': original_partner_ids})
+ return thread_id
+
+ @api.model
+ def message_process(self, model, message, custom_values=None,
+ save_original=False, strip_attachments=False,
+ thread_id=None):
+ """ Process an incoming RFC2822 email message, relying on
+ ``mail.message.parse()`` for the parsing operation,
+ and ``message_route()`` to figure out the target model.
+
+ Once the target model is known, its ``message_new`` method
+ is called with the new message (if the thread record did not exist)
+ or its ``message_update`` method (if it did).
+
+ :param string model: the fallback model to use if the message
+ does not match any of the currently configured mail aliases
+ (may be None if a matching alias is supposed to be present)
+ :param message: source of the RFC2822 message
+ :type message: string or xmlrpclib.Binary
+ :type dict custom_values: optional dictionary of field values
+ to pass to ``message_new`` if a new record needs to be created.
+ Ignored if the thread record already exists, and also if a
+ matching mail.alias was found (aliases define their own defaults)
+ :param bool save_original: whether to keep a copy of the original
+ email source attached to the message after it is imported.
+ :param bool strip_attachments: whether to strip all attachments
+ before processing the message, in order to save some space.
+ :param int thread_id: optional ID of the record/thread from ``model``
+ to which this mail should be attached. When provided, this
+ overrides the automatic detection based on the message
+ headers.
+ """
+ # extract message bytes - we are forced to pass the message as binary because
+ # we don't know its encoding until we parse its headers and hence can't
+ # convert it to utf-8 for transport between the mailgate script and here.
+ if isinstance(message, xmlrpclib.Binary):
+ message = bytes(message.data)
+ if isinstance(message, str):
+ message = message.encode('utf-8')
+ message = email.message_from_bytes(message, policy=email.policy.SMTP)
+
+ # parse the message, verify we are not in a loop by checking message_id is not duplicated
+ msg_dict = self.message_parse(message, save_original=save_original)
+ if strip_attachments:
+ msg_dict.pop('attachments', None)
+
+ existing_msg_ids = self.env['mail.message'].search([('message_id', '=', msg_dict['message_id'])], limit=1)
+ if existing_msg_ids:
+ _logger.info('Ignored mail from %s to %s with Message-Id %s: found duplicated Message-Id during processing',
+ msg_dict.get('email_from'), msg_dict.get('to'), msg_dict.get('message_id'))
+ return False
+
+ # find possible routes for the message
+ routes = self.message_route(message, msg_dict, model, thread_id, custom_values)
+ thread_id = self._message_route_process(message, msg_dict, routes)
+ return thread_id
+
+ @api.model
+ def message_new(self, msg_dict, custom_values=None):
+ """Called by ``message_process`` when a new message is received
+ for a given thread model, if the message did not belong to
+ an existing thread.
+ The default behavior is to create a new record of the corresponding
+ model (based on some very basic info extracted from the message).
+ Additional behavior may be implemented by overriding this method.
+
+ :param dict msg_dict: a map containing the email details and
+ attachments. See ``message_process`` and
+ ``mail.message.parse`` for details.
+ :param dict custom_values: optional dictionary of additional
+ field values to pass to create()
+ when creating the new thread record.
+ Be careful, these values may override
+ any other values coming from the message.
+ :rtype: int
+ :return: the id of the newly created thread object
+ """
+ data = {}
+ if isinstance(custom_values, dict):
+ data = custom_values.copy()
+ fields = self.fields_get()
+ name_field = self._rec_name or 'name'
+ if name_field in fields and not data.get('name'):
+ data[name_field] = msg_dict.get('subject', '')
+ return self.create(data)
+
+ def message_update(self, msg_dict, update_vals=None):
+ """Called by ``message_process`` when a new message is received
+ for an existing thread. The default behavior is to update the record
+ with update_vals taken from the incoming email.
+ Additional behavior may be implemented by overriding this
+ method.
+ :param dict msg_dict: a map containing the email details and
+ attachments. See ``message_process`` and
+ ``mail.message.parse()`` for details.
+ :param dict update_vals: a dict containing values to update records
+ given their ids; if the dict is None or is
+ void, no write operation is performed.
+ """
+ if update_vals:
+ self.write(update_vals)
+ return True
+
+ def _message_receive_bounce(self, email, partner):
+ """Called by ``message_process`` when a bounce email (such as Undelivered
+ Mail Returned to Sender) is received for an existing thread. The default
+ behavior is to do nothing. This method is meant to be overridden in various
+ modules to add some specific behavior like blacklist management or mass
+ mailing statistics update. check is an integer ``message_bounce`` column exists.
+ If it is the case, its content is incremented.
+
+ :param string email: email that caused the bounce;
+ :param record partner: partner matching the bounced email address, if any;
+ """
+ pass
+
+ def _message_reset_bounce(self, email):
+ """Called by ``message_process`` when an email is considered as not being
+ a bounce. The default behavior is to do nothing. This method is meant to
+ be overridden in various modules to add some specific behavior like
+ blacklist management.
+
+ :param string email: email for which to reset bounce information
+ """
+ pass
+
+ def _message_parse_extract_payload_postprocess(self, message, payload_dict):
+ """ Perform some cleaning / postprocess in the body and attachments
+ extracted from the email. Note that this processing is specific to the
+ mail module, and should not contain security or generic html cleaning.
+ Indeed those aspects should be covered by the html_sanitize method
+ located in tools. """
+ body, attachments = payload_dict['body'], payload_dict['attachments']
+ if not body:
+ return payload_dict
+ try:
+ root = lxml.html.fromstring(body)
+ except ValueError:
+ # In case the email client sent XHTML, fromstring will fail because 'Unicode strings
+ # with encoding declaration are not supported'.
+ root = lxml.html.fromstring(body.encode('utf-8'))
+
+ postprocessed = False
+ to_remove = []
+ for node in root.iter():
+ if 'o_mail_notification' in (node.get('class') or '') or 'o_mail_notification' in (node.get('summary') or ''):
+ postprocessed = True
+ if node.getparent() is not None:
+ to_remove.append(node)
+ if node.tag == 'img' and node.get('src', '').startswith('cid:'):
+ cid = node.get('src').split(':', 1)[1]
+ related_attachment = [attach for attach in attachments if attach[2] and attach[2].get('cid') == cid]
+ if related_attachment:
+ node.set('data-filename', related_attachment[0][0])
+ postprocessed = True
+
+ for node in to_remove:
+ node.getparent().remove(node)
+ if postprocessed:
+ body = etree.tostring(root, pretty_print=False, encoding='unicode')
+ return {'body': body, 'attachments': attachments}
+
+ def _message_parse_extract_payload(self, message, save_original=False):
+ """Extract body as HTML and attachments from the mail message"""
+ attachments = []
+ body = u''
+ if save_original:
+ attachments.append(self._Attachment('original_email.eml', message.as_string(), {}))
+
+ # Be careful, content-type may contain tricky content like in the
+ # following example so test the MIME type with startswith()
+ #
+ # Content-Type: multipart/related;
+ # boundary="_004_3f1e4da175f349248b8d43cdeb9866f1AMSPR06MB343eurprd06pro_";
+ # type="text/html"
+ if message.get_content_maintype() == 'text':
+ encoding = message.get_content_charset()
+ body = message.get_content()
+ body = tools.ustr(body, encoding, errors='replace')
+ if message.get_content_type() == 'text/plain':
+ # text/plain ->
+ body = tools.append_content_to_html(u'', body, preserve=True)
+ else:
+ alternative = False
+ mixed = False
+ html = u''
+ for part in message.walk():
+ if part.get_content_type() == 'multipart/alternative':
+ alternative = True
+ if part.get_content_type() == 'multipart/mixed':
+ mixed = True
+ if part.get_content_maintype() == 'multipart':
+ continue # skip container
+
+ filename = part.get_filename() # I may not properly handle all charsets
+ encoding = part.get_content_charset() # None if attachment
+
+ # 0) Inline Attachments -> attachments, with a third part in the tuple to match cid / attachment
+ if filename and part.get('content-id'):
+ inner_cid = part.get('content-id').strip('><')
+ attachments.append(self._Attachment(filename, part.get_content(), {'cid': inner_cid}))
+ continue
+ # 1) Explicit Attachments -> attachments
+ if filename or part.get('content-disposition', '').strip().startswith('attachment'):
+ attachments.append(self._Attachment(filename or 'attachment', part.get_content(), {}))
+ continue
+ # 2) text/plain ->
+ if part.get_content_type() == 'text/plain' and (not alternative or not body):
+ body = tools.append_content_to_html(body, tools.ustr(part.get_content(),
+ encoding, errors='replace'), preserve=True)
+ # 3) text/html -> raw
+ elif part.get_content_type() == 'text/html':
+ # mutlipart/alternative have one text and a html part, keep only the second
+ # mixed allows several html parts, append html content
+ append_content = not alternative or (html and mixed)
+ html = tools.ustr(part.get_content(), encoding, errors='replace')
+ if not append_content:
+ body = html
+ else:
+ body = tools.append_content_to_html(body, html, plaintext=False)
+ # we only strip_classes here everything else will be done in by html field of mail.message
+ body = tools.html_sanitize(body, sanitize_tags=False, strip_classes=True)
+ # 4) Anything else -> attachment
+ else:
+ attachments.append(self._Attachment(filename or 'attachment', part.get_content(), {}))
+
+ return self._message_parse_extract_payload_postprocess(message, {'body': body, 'attachments': attachments})
+
+ def _message_parse_extract_bounce(self, email_message, message_dict):
+ """ Parse email and extract bounce information to be used in future
+ processing.
+
+ :param email_message: an email.message instance;
+ :param message_dict: dictionary holding already-parsed values;
+
+ :return dict: bounce-related values will be added, containing
+
+ * bounced_email: email that bounced (normalized);
+ * bounce_partner: res.partner recordset whose email_normalized =
+ bounced_email;
+ * bounced_msg_id: list of message_ID references (<...@myserver>) linked
+ to the email that bounced;
+ * bounced_message: if found, mail.message recordset matching bounced_msg_id;
+ """
+ if not isinstance(email_message, EmailMessage):
+ raise TypeError('message must be an email.message.EmailMessage at this point')
+
+ email_part = next((part for part in email_message.walk() if part.get_content_type() in {'message/rfc822', 'text/rfc822-headers'}), None)
+ dsn_part = next((part for part in email_message.walk() if part.get_content_type() == 'message/delivery-status'), None)
+
+ bounced_email = False
+ bounced_partner = self.env['res.partner'].sudo()
+ if dsn_part and len(dsn_part.get_payload()) > 1:
+ dsn = dsn_part.get_payload()[1]
+ final_recipient_data = tools.decode_message_header(dsn, 'Final-Recipient')
+ bounced_email = tools.email_normalize(final_recipient_data.split(';', 1)[1].strip())
+ if bounced_email:
+ bounced_partner = self.env['res.partner'].sudo().search([('email_normalized', '=', bounced_email)])
+
+ bounced_msg_id = False
+ bounced_message = self.env['mail.message'].sudo()
+ if email_part:
+ if email_part.get_content_type() == 'text/rfc822-headers':
+ # Convert the message body into a message itself
+ email_payload = message_from_string(email_part.get_payload(), policy=policy.SMTP)
+ else:
+ email_payload = email_part.get_payload()[0]
+ bounced_msg_id = tools.mail_header_msgid_re.findall(tools.decode_message_header(email_payload, 'Message-Id'))
+ if bounced_msg_id:
+ bounced_message = self.env['mail.message'].sudo().search([('message_id', 'in', bounced_msg_id)])
+
+ return {
+ 'bounced_email': bounced_email,
+ 'bounced_partner': bounced_partner,
+ 'bounced_msg_id': bounced_msg_id,
+ 'bounced_message': bounced_message,
+ }
+
+ @api.model
+ def message_parse(self, message, save_original=False):
+ """ Parses an email.message.Message representing an RFC-2822 email
+ and returns a generic dict holding the message details.
+
+ :param message: email to parse
+ :type message: email.message.Message
+ :param bool save_original: whether the returned dict should include
+ an ``original`` attachment containing the source of the message
+ :rtype: dict
+ :return: A dict with the following structure, where each field may not
+ be present if missing in original message::
+
+ { 'message_id': msg_id,
+ 'subject': subject,
+ 'email_from': from,
+ 'to': to + delivered-to,
+ 'cc': cc,
+ 'recipients': delivered-to + to + cc + resent-to + resent-cc,
+ 'partner_ids': partners found based on recipients emails,
+ 'body': unified_body,
+ 'references': references,
+ 'in_reply_to': in-reply-to,
+ 'parent_id': parent mail.message based on in_reply_to or references,
+ 'is_internal': answer to an internal message (note),
+ 'date': date,
+ 'attachments': [('file1', 'bytes'),
+ ('file2', 'bytes')}
+ }
+ """
+ if not isinstance(message, EmailMessage):
+ raise ValueError(_('Message should be a valid EmailMessage instance'))
+ msg_dict = {'message_type': 'email'}
+
+ message_id = message.get('Message-Id')
+ if not message_id:
+ # Very unusual situation, be we should be fault-tolerant here
+ message_id = "<%s@localhost>" % time.time()
+ _logger.debug('Parsing Message without message-id, generating a random one: %s', message_id)
+ msg_dict['message_id'] = message_id.strip()
+
+ if message.get('Subject'):
+ msg_dict['subject'] = tools.decode_message_header(message, 'Subject')
+
+ email_from = tools.decode_message_header(message, 'From')
+ email_cc = tools.decode_message_header(message, 'cc')
+ email_from_list = tools.email_split_and_format(email_from)
+ email_cc_list = tools.email_split_and_format(email_cc)
+ msg_dict['email_from'] = email_from_list[0] if email_from_list else email_from
+ msg_dict['from'] = msg_dict['email_from'] # compatibility for message_new
+ msg_dict['cc'] = ','.join(email_cc_list) if email_cc_list else email_cc
+ # Delivered-To is a safe bet in most modern MTAs, but we have to fallback on To + Cc values
+ # for all the odd MTAs out there, as there is no standard header for the envelope's `rcpt_to` value.
+ msg_dict['recipients'] = ','.join(set(formatted_email
+ for address in [
+ tools.decode_message_header(message, 'Delivered-To'),
+ tools.decode_message_header(message, 'To'),
+ tools.decode_message_header(message, 'Cc'),
+ tools.decode_message_header(message, 'Resent-To'),
+ tools.decode_message_header(message, 'Resent-Cc')
+ ] if address
+ for formatted_email in tools.email_split_and_format(address))
+ )
+ msg_dict['to'] = ','.join(set(formatted_email
+ for address in [
+ tools.decode_message_header(message, 'Delivered-To'),
+ tools.decode_message_header(message, 'To')
+ ] if address
+ for formatted_email in tools.email_split_and_format(address))
+ )
+ partner_ids = [x.id for x in self._mail_find_partner_from_emails(tools.email_split(msg_dict['recipients']), records=self) if x]
+ msg_dict['partner_ids'] = partner_ids
+ # compute references to find if email_message is a reply to an existing thread
+ msg_dict['references'] = tools.decode_message_header(message, 'References')
+ msg_dict['in_reply_to'] = tools.decode_message_header(message, 'In-Reply-To').strip()
+
+ if message.get('Date'):
+ try:
+ date_hdr = tools.decode_message_header(message, 'Date')
+ parsed_date = dateutil.parser.parse(date_hdr, fuzzy=True)
+ if parsed_date.utcoffset() is None:
+ # naive datetime, so we arbitrarily decide to make it
+ # UTC, there's no better choice. Should not happen,
+ # as RFC2822 requires timezone offset in Date headers.
+ stored_date = parsed_date.replace(tzinfo=pytz.utc)
+ else:
+ stored_date = parsed_date.astimezone(tz=pytz.utc)
+ except Exception:
+ _logger.info('Failed to parse Date header %r in incoming mail '
+ 'with message-id %r, assuming current date/time.',
+ message.get('Date'), message_id)
+ stored_date = datetime.datetime.now()
+ msg_dict['date'] = stored_date.strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT)
+
+ parent_ids = False
+ if msg_dict['in_reply_to']:
+ parent_ids = self.env['mail.message'].search([('message_id', '=', msg_dict['in_reply_to'])], limit=1)
+ if msg_dict['references'] and not parent_ids:
+ references_msg_id_list = tools.mail_header_msgid_re.findall(msg_dict['references'])
+ parent_ids = self.env['mail.message'].search([('message_id', 'in', [x.strip() for x in references_msg_id_list])], limit=1)
+ if parent_ids:
+ msg_dict['parent_id'] = parent_ids.id
+ msg_dict['is_internal'] = parent_ids.subtype_id and parent_ids.subtype_id.internal or False
+
+ msg_dict.update(self._message_parse_extract_payload(message, save_original=save_original))
+ msg_dict.update(self._message_parse_extract_bounce(message, msg_dict))
+ return msg_dict
+
+ # ------------------------------------------------------
+ # RECIPIENTS MANAGEMENT TOOLS
+ # ------------------------------------------------------
+
+ @api.model
+ def _message_get_default_recipients_on_records(self, records):
+ """ Moved to ``BaseModel._message_get_default_recipients()`` """
+ return records._message_get_default_recipients()
+
+ def _message_add_suggested_recipient(self, result, partner=None, email=None, reason=''):
+ """ Called by _message_get_suggested_recipients, to add a suggested
+ recipient in the result dictionary. The form is :
+ partner_id, partner_name or partner_name, reason """
+ self.ensure_one()
+ if email and not partner:
+ # get partner info from email
+ partner_info = self._message_partner_info_from_emails([email])[0]
+ if partner_info.get('partner_id'):
+ partner = self.env['res.partner'].sudo().browse([partner_info['partner_id']])[0]
+ if email and email in [val[1] for val in result[self.ids[0]]]: # already existing email -> skip
+ return result
+ if partner and partner in self.message_partner_ids: # recipient already in the followers -> skip
+ return result
+ if partner and partner.id in [val[0] for val in result[self.ids[0]]]: # already existing partner ID -> skip
+ return result
+ if partner and partner.email: # complete profile: id, name
+ result[self.ids[0]].append((partner.id, partner.email_formatted, reason))
+ elif partner: # incomplete profile: id, name
+ result[self.ids[0]].append((partner.id, '%s' % (partner.name), reason))
+ else: # unknown partner, we are probably managing an email address
+ result[self.ids[0]].append((False, email, reason))
+ return result
+
+ def _message_get_suggested_recipients(self):
+ """ Returns suggested recipients for ids. Those are a list of
+ tuple (partner_id, partner_name, reason), to be managed by Chatter. """
+ result = dict((res_id, []) for res_id in self.ids)
+ if 'user_id' in self._fields:
+ for obj in self.sudo(): # SUPERUSER because of a read on res.users that would crash otherwise
+ if not obj.user_id or not obj.user_id.partner_id:
+ continue
+ obj._message_add_suggested_recipient(result, partner=obj.user_id.partner_id, reason=self._fields['user_id'].string)
+ return result
+
+ def _mail_search_on_user(self, normalized_emails, extra_domain=False):
+ """ Find partners linked to users, given an email address that will
+ be normalized. Search is done as sudo on res.users model to avoid domain
+ on partner like ('user_ids', '!=', False) that would not be efficient. """
+ domain = [('email_normalized', 'in', normalized_emails)]
+ if extra_domain:
+ domain = expression.AND([domain, extra_domain])
+ partners = self.env['res.users'].sudo().search(domain, order='name ASC').mapped('partner_id')
+ # return a search on partner to filter results current user should not see (multi company for example)
+ return self.env['res.partner'].search([('id', 'in', partners.ids)])
+
+ def _mail_search_on_partner(self, normalized_emails, extra_domain=False):
+ domain = [('email_normalized', 'in', normalized_emails)]
+ if extra_domain:
+ domain = expression.AND([domain, extra_domain])
+ return self.env['res.partner'].search(domain)
+
+ def _mail_find_user_for_gateway(self, email, alias=None):
+ """ Utility method to find user from email address that can create documents
+ in the target model. Purpose is to link document creation to users whenever
+ possible, for example when creating document through mailgateway.
+
+ Heuristic
+
+ * alias owner record: fetch in its followers for user with matching email;
+ * find any user with matching emails;
+ * try alias owner as fallback;
+
+ Note that standard search order is applied.
+
+ :param str email: will be sanitized and parsed to find email;
+ :param mail.alias alias: optional alias. Used to fetch owner followers
+ or fallback user (alias owner);
+ :param fallback_model: if not alias, related model to check access rights;
+
+ :return res.user user: user matching email or void recordset if none found
+ """
+ # find normalized emails and exclude aliases (to avoid subscribing alias emails to records)
+ normalized_email = tools.email_normalize(email)
+ catchall_domain = self.env['ir.config_parameter'].sudo().get_param("mail.catchall.domain")
+ if normalized_email and catchall_domain:
+ left_part = normalized_email.split('@')[0] if normalized_email.split('@')[1] == catchall_domain.lower() else False
+ if left_part:
+ if self.env['mail.alias'].sudo().search_count([('alias_name', '=', left_part)]):
+ return self.env['res.users']
+
+ if alias and alias.alias_parent_model_id and alias.alias_parent_thread_id:
+ followers = self.env['mail.followers'].search([
+ ('res_model', '=', alias.alias_parent_model_id.model),
+ ('res_id', '=', alias.alias_parent_thread_id)]
+ ).mapped('partner_id')
+ else:
+ followers = self.env['res.partner']
+
+ follower_users = self.env['res.users'].search([
+ ('partner_id', 'in', followers.ids), ('email_normalized', '=', normalized_email)
+ ], limit=1) if followers else self.env['res.users']
+ matching_user = follower_users[0] if follower_users else self.env['res.users']
+ if matching_user:
+ return matching_user
+
+ if not matching_user:
+ std_users = self.env['res.users'].sudo().search([('email_normalized', '=', normalized_email)], limit=1, order='name ASC')
+ matching_user = std_users[0] if std_users else self.env['res.users']
+ if matching_user:
+ return matching_user
+
+ if not matching_user and alias and alias.alias_user_id:
+ matching_user = alias and alias.alias_user_id
+ if matching_user:
+ return matching_user
+
+ return matching_user
+
+ @api.model
+ def _mail_find_partner_from_emails(self, emails, records=None, force_create=False):
+ """ Utility method to find partners from email addresses. If no partner is
+ found, create new partners if force_create is enabled. Search heuristics
+
+ * 1: check in records (record set) followers if records is mail.thread
+ enabled and if check_followers parameter is enabled;
+ * 2: search for partners with user;
+ * 3: search for partners;
+
+ :param records: record set on which to check followers;
+ :param list emails: list of email addresses for finding partner;
+ :param boolean force_create: create a new partner if not found
+
+ :return list partners: a list of partner records ordered as given emails.
+ If no partner has been found and/or created for a given emails its
+ matching partner is an empty record.
+ """
+ if records and issubclass(type(records), self.pool['mail.thread']):
+ followers = records.mapped('message_partner_ids')
+ else:
+ followers = self.env['res.partner']
+ catchall_domain = self.env['ir.config_parameter'].sudo().get_param("mail.catchall.domain")
+
+ # first, build a normalized email list and remove those linked to aliases to avoid adding aliases as partners
+ normalized_emails = [tools.email_normalize(contact) for contact in emails if tools.email_normalize(contact)]
+ if catchall_domain:
+ domain_left_parts = [email.split('@')[0] for email in normalized_emails if email and email.split('@')[1] == catchall_domain.lower()]
+ if domain_left_parts:
+ found_alias_names = self.env['mail.alias'].sudo().search([('alias_name', 'in', domain_left_parts)]).mapped('alias_name')
+ normalized_emails = [email for email in normalized_emails if email.split('@')[0] not in found_alias_names]
+
+ done_partners = [follower for follower in followers if follower.email_normalized in normalized_emails]
+ remaining = [email for email in normalized_emails if email not in [partner.email_normalized for partner in done_partners]]
+
+ user_partners = self._mail_search_on_user(remaining)
+ done_partners += [user_partner for user_partner in user_partners]
+ remaining = [email for email in normalized_emails if email not in [partner.email_normalized for partner in done_partners]]
+
+ partners = self._mail_search_on_partner(remaining)
+ done_partners += [partner for partner in partners]
+ remaining = [email for email in normalized_emails if email not in [partner.email_normalized for partner in done_partners]]
+
+ # iterate and keep ordering
+ partners = []
+ for contact in emails:
+ normalized_email = tools.email_normalize(contact)
+ partner = next((partner for partner in done_partners if partner.email_normalized == normalized_email), self.env['res.partner'])
+ if not partner and force_create and normalized_email in normalized_emails:
+ partner = self.env['res.partner'].browse(self.env['res.partner'].name_create(contact)[0])
+ partners.append(partner)
+ return partners
+
+ def _message_partner_info_from_emails(self, emails, link_mail=False):
+ """ Convert a list of emails into a list partner_ids and a list
+ new_partner_ids. The return value is non conventional because
+ it is meant to be used by the mail widget.
+
+ :return dict: partner_ids and new_partner_ids """
+ self.ensure_one()
+ MailMessage = self.env['mail.message'].sudo()
+ partners = self._mail_find_partner_from_emails(emails, records=self)
+ result = list()
+ for idx, contact in enumerate(emails):
+ partner = partners[idx]
+ partner_info = {'full_name': partner.email_formatted if partner else contact, 'partner_id': partner.id}
+ result.append(partner_info)
+ # link mail with this from mail to the new partner id
+ if link_mail and partner:
+ MailMessage.search([
+ ('email_from', '=ilike', partner.email_normalized),
+ ('author_id', '=', False)
+ ]).write({'author_id': partner.id})
+ return result
+
+ # ------------------------------------------------------
+ # MESSAGE POST API
+ # ------------------------------------------------------
+
+ def _message_post_process_attachments(self, attachments, attachment_ids, message_values):
+ """ Preprocess attachments for mail_thread.message_post() or mail_mail.create().
+
+ :param list attachments: list of attachment tuples in the form ``(name,content)``, #todo xdo update that
+ where content is NOT base64 encoded
+ :param list attachment_ids: a list of attachment ids, not in tomany command form
+ :param dict message_data: model: the model of the attachments parent record,
+ res_id: the id of the attachments parent record
+ """
+ return_values = {}
+ body = message_values.get('body')
+ model = message_values['model']
+ res_id = message_values['res_id']
+
+ m2m_attachment_ids = []
+ if attachment_ids:
+ # taking advantage of cache looks better in this case, to check
+ filtered_attachment_ids = self.env['ir.attachment'].sudo().browse(attachment_ids).filtered(
+ lambda a: a.res_model == 'mail.compose.message' and a.create_uid.id == self._uid)
+ # update filtered (pending) attachments to link them to the proper record
+ if filtered_attachment_ids:
+ filtered_attachment_ids.write({'res_model': model, 'res_id': res_id})
+ # prevent public and portal users from using attachments that are not theirs
+ if not self.env.user.has_group('base.group_user'):
+ attachment_ids = filtered_attachment_ids.ids
+
+ m2m_attachment_ids += [(4, id) for id in attachment_ids]
+ # Handle attachments parameter, that is a dictionary of attachments
+
+ if attachments: # generate
+ cids_in_body = set()
+ names_in_body = set()
+ cid_list = []
+ name_list = []
+
+ if body:
+ root = lxml.html.fromstring(tools.ustr(body))
+ # first list all attachments that will be needed in body
+ for node in root.iter('img'):
+ if node.get('src', '').startswith('cid:'):
+ cids_in_body.add(node.get('src').split('cid:')[1])
+ elif node.get('data-filename'):
+ names_in_body.add(node.get('data-filename'))
+ attachement_values_list = []
+
+ # generate values
+ for attachment in attachments:
+ cid = False
+ if len(attachment) == 2:
+ name, content = attachment
+ elif len(attachment) == 3:
+ name, content, info = attachment
+ cid = info and info.get('cid')
+ else:
+ continue
+ if isinstance(content, str):
+ content = content.encode('utf-8')
+ elif isinstance(content, EmailMessage):
+ content = content.as_bytes()
+ elif content is None:
+ continue
+ attachement_values= {
+ 'name': name,
+ 'datas': base64.b64encode(content),
+ 'type': 'binary',
+ 'description': name,
+ 'res_model': model,
+ 'res_id': res_id,
+ }
+ if body and (cid and cid in cids_in_body or name in names_in_body):
+ attachement_values['access_token'] = self.env['ir.attachment']._generate_access_token()
+ attachement_values_list.append(attachement_values)
+ # keep cid and name list synced with attachement_values_list length to match ids latter
+ cid_list.append(cid)
+ name_list.append(name)
+ new_attachments = self.env['ir.attachment'].create(attachement_values_list)
+ cid_mapping = {}
+ name_mapping = {}
+ for counter, new_attachment in enumerate(new_attachments):
+ cid = cid_list[counter]
+ if 'access_token' in attachement_values_list[counter]:
+ if cid:
+ cid_mapping[cid] = (new_attachment.id, attachement_values_list[counter]['access_token'])
+ name = name_list[counter]
+ name_mapping[name] = (new_attachment.id, attachement_values_list[counter]['access_token'])
+ m2m_attachment_ids.append((4, new_attachment.id))
+
+ # note: right know we are only taking attachments and ignoring attachment_ids.
+ if (cid_mapping or name_mapping) and body:
+ postprocessed = False
+ for node in root.iter('img'):
+ attachment_data = False
+ if node.get('src', '').startswith('cid:'):
+ cid = node.get('src').split('cid:')[1]
+ attachment_data = cid_mapping.get(cid)
+ if not attachment_data and node.get('data-filename'):
+ attachment_data = name_mapping.get(node.get('data-filename'), False)
+ if attachment_data:
+ node.set('src', '/web/image/%s?access_token=%s' % attachment_data)
+ postprocessed = True
+ if postprocessed:
+ return_values['body'] = lxml.html.tostring(root, pretty_print=False, encoding='UTF-8')
+ return_values['attachment_ids'] = m2m_attachment_ids
+ return return_values
+
+ @api.returns('mail.message', lambda value: value.id)
+ def message_post(self, *,
+ body='', subject=None, message_type='notification',
+ email_from=None, author_id=None, parent_id=False,
+ subtype_xmlid=None, subtype_id=False, partner_ids=None, channel_ids=None,
+ attachments=None, attachment_ids=None,
+ add_sign=True, record_name=False,
+ **kwargs):
+ """ Post a new message in an existing thread, returning the new
+ mail.message ID.
+ :param str body: body of the message, usually raw HTML that will
+ be sanitized
+ :param str subject: subject of the message
+ :param str message_type: see mail_message.message_type field. Can be anything but
+ user_notification, reserved for message_notify
+ :param int parent_id: handle thread formation
+ :param int subtype_id: subtype_id of the message, mainly use fore
+ followers mechanism
+ :param list(int) partner_ids: partner_ids to notify
+ :param list(int) channel_ids: channel_ids to notify
+ :param list(tuple(str,str), tuple(str,str, dict) or int) attachments : list of attachment tuples in the form
+ ``(name,content)`` or ``(name,content, info)``, where content is NOT base64 encoded
+ :param list id attachment_ids: list of existing attachement to link to this message
+ -Should only be setted by chatter
+ -Attachement object attached to mail.compose.message(0) will be attached
+ to the related document.
+ Extra keyword arguments will be used as default column values for the
+ new mail.message record.
+ :return int: ID of newly created mail.message
+ """
+ self.ensure_one() # should always be posted on a record, use message_notify if no record
+ # split message additional values from notify additional values
+ msg_kwargs = dict((key, val) for key, val in kwargs.items() if key in self.env['mail.message']._fields)
+ notif_kwargs = dict((key, val) for key, val in kwargs.items() if key not in msg_kwargs)
+
+ if self._name == 'mail.thread' or not self.id or message_type == 'user_notification':
+ raise ValueError('message_post should only be call to post message on record. Use message_notify instead')
+
+ if 'model' in msg_kwargs or 'res_id' in msg_kwargs:
+ raise ValueError("message_post doesn't support model and res_id parameters anymore. Please call message_post on record.")
+ if 'subtype' in kwargs:
+ raise ValueError("message_post doesn't support subtype parameter anymore. Please give a valid subtype_id or subtype_xmlid value instead.")
+
+ self = self._fallback_lang() # add lang to context imediatly since it will be usefull in various flows latter.
+
+ # Explicit access rights check, because display_name is computed as sudo.
+ self.check_access_rights('read')
+ self.check_access_rule('read')
+ record_name = record_name or self.display_name
+
+ partner_ids = set(partner_ids or [])
+ channel_ids = set(channel_ids or [])
+
+ if any(not isinstance(pc_id, int) for pc_id in partner_ids | channel_ids):
+ raise ValueError('message_post partner_ids and channel_ids must be integer list, not commands')
+
+ # Find the message's author
+ author_id, email_from = self._message_compute_author(author_id, email_from, raise_exception=True)
+
+ if subtype_xmlid:
+ subtype_id = self.env['ir.model.data'].xmlid_to_res_id(subtype_xmlid)
+ if not subtype_id:
+ subtype_id = self.env['ir.model.data'].xmlid_to_res_id('mail.mt_note')
+
+ # automatically subscribe recipients if asked to
+ if self._context.get('mail_post_autofollow') and partner_ids:
+ self.message_subscribe(list(partner_ids))
+
+ MailMessage_sudo = self.env['mail.message'].sudo()
+ if self._mail_flat_thread and not parent_id:
+ parent_message = MailMessage_sudo.search([('res_id', '=', self.id), ('model', '=', self._name), ('message_type', '!=', 'user_notification')], order="id ASC", limit=1)
+ # parent_message searched in sudo for performance, only used for id.
+ # Note that with sudo we will match message with internal subtypes.
+ parent_id = parent_message.id if parent_message else False
+ elif parent_id:
+ old_parent_id = parent_id
+ parent_message = MailMessage_sudo.search([('id', '=', parent_id), ('parent_id', '!=', False)], limit=1)
+ # avoid loops when finding ancestors
+ processed_list = []
+ if parent_message:
+ new_parent_id = parent_message.parent_id and parent_message.parent_id.id
+ while (new_parent_id and new_parent_id not in processed_list):
+ processed_list.append(new_parent_id)
+ parent_message = parent_message.parent_id
+ parent_id = parent_message.id
+
+ values = dict(msg_kwargs)
+ values.update({
+ 'author_id': author_id,
+ 'email_from': email_from,
+ 'model': self._name,
+ 'res_id': self.id,
+ 'body': body,
+ 'subject': subject or False,
+ 'message_type': message_type,
+ 'parent_id': parent_id,
+ 'subtype_id': subtype_id,
+ 'partner_ids': partner_ids,
+ 'channel_ids': channel_ids,
+ 'add_sign': add_sign,
+ 'record_name': record_name,
+ })
+ attachments = attachments or []
+ attachment_ids = attachment_ids or []
+ attachement_values = self._message_post_process_attachments(attachments, attachment_ids, values)
+ values.update(attachement_values) # attachement_ids, [body]
+
+ new_message = self._message_create(values)
+
+ # Set main attachment field if necessary
+ self._message_set_main_attachment_id(values['attachment_ids'])
+
+ if values['author_id'] and values['message_type'] != 'notification' and not self._context.get('mail_create_nosubscribe'):
+ if self.env['res.partner'].browse(values['author_id']).active: # we dont want to add odoobot/inactive as a follower
+ self._message_subscribe([values['author_id']])
+
+ self._message_post_after_hook(new_message, values)
+ self._notify_thread(new_message, values, **notif_kwargs)
+ return new_message
+
+ def _message_set_main_attachment_id(self, attachment_ids): # todo move this out of mail.thread
+ if not self._abstract and attachment_ids and not self.message_main_attachment_id:
+ all_attachments = self.env['ir.attachment'].browse([attachment_tuple[1] for attachment_tuple in attachment_ids])
+ prioritary_attachments = all_attachments.filtered(lambda x: x.mimetype.endswith('pdf')) \
+ or all_attachments.filtered(lambda x: x.mimetype.startswith('image')) \
+ or all_attachments
+ self.sudo().with_context(tracking_disable=True).write({'message_main_attachment_id': prioritary_attachments[0].id})
+
+ def _message_post_after_hook(self, message, msg_vals):
+ """ Hook to add custom behavior after having posted the message. Both
+ message and computed value are given, to try to lessen query count by
+ using already-computed values instead of having to rebrowse things. """
+ pass
+
+ # ------------------------------------------------------
+ # MESSAGE POST TOOLS
+ # ------------------------------------------------------
+
+ def message_post_with_view(self, views_or_xmlid, **kwargs):
+ """ Helper method to send a mail / post a message using a view_id to
+ render using the ir.qweb engine. This method is stand alone, because
+ there is nothing in template and composer that allows to handle
+ views in batch. This method should probably disappear when templates
+ handle ir ui views. """
+ values = kwargs.pop('values', None) or dict()
+ try:
+ from odoo.addons.http_routing.models.ir_http import slug
+ values['slug'] = slug
+ except ImportError:
+ values['slug'] = lambda self: self.id
+ if isinstance(views_or_xmlid, str):
+ views = self.env.ref(views_or_xmlid, raise_if_not_found=False)
+ else:
+ views = views_or_xmlid
+ if not views:
+ return
+ for record in self:
+ values['object'] = record
+ rendered_template = views._render(values, engine='ir.qweb', minimal_qcontext=True)
+ kwargs['body'] = rendered_template
+ record.message_post_with_template(False, **kwargs)
+
+ def message_post_with_template(self, template_id, email_layout_xmlid=None, auto_commit=False, **kwargs):
+ """ Helper method to send a mail with a template
+ :param template_id : the id of the template to render to create the body of the message
+ :param **kwargs : parameter to create a mail.compose.message woaerd (which inherit from mail.message)
+ """
+ # Get composition mode, or force it according to the number of record in self
+ if not kwargs.get('composition_mode'):
+ kwargs['composition_mode'] = 'comment' if len(self.ids) == 1 else 'mass_mail'
+ if not kwargs.get('message_type'):
+ kwargs['message_type'] = 'notification'
+ res_id = kwargs.get('res_id', self.ids and self.ids[0] or 0)
+ res_ids = kwargs.get('res_id') and [kwargs['res_id']] or self.ids
+
+ # Create the composer
+ composer = self.env['mail.compose.message'].with_context(
+ active_id=res_id,
+ active_ids=res_ids,
+ active_model=kwargs.get('model', self._name),
+ default_composition_mode=kwargs['composition_mode'],
+ default_model=kwargs.get('model', self._name),
+ default_res_id=res_id,
+ default_template_id=template_id,
+ custom_layout=email_layout_xmlid,
+ ).create(kwargs)
+ # Simulate the onchange (like trigger in form the view) only
+ # when having a template in single-email mode
+ if template_id:
+ update_values = composer.onchange_template_id(template_id, kwargs['composition_mode'], self._name, res_id)['value']
+ composer.write(update_values)
+ return composer.send_mail(auto_commit=auto_commit)
+
+ def message_notify(self, *,
+ partner_ids=False, parent_id=False, model=False, res_id=False,
+ author_id=None, email_from=None, body='', subject=False, **kwargs):
+ """ Shortcut allowing to notify partners of messages that shouldn't be
+ displayed on a document. It pushes notifications on inbox or by email depending
+ on the user configuration, like other notifications. """
+ if self:
+ self.ensure_one()
+ # split message additional values from notify additional values
+ msg_kwargs = dict((key, val) for key, val in kwargs.items() if key in self.env['mail.message']._fields)
+ notif_kwargs = dict((key, val) for key, val in kwargs.items() if key not in msg_kwargs)
+
+ author_id, email_from = self._message_compute_author(author_id, email_from, raise_exception=True)
+
+ if not partner_ids:
+ _logger.warning('Message notify called without recipient_ids, skipping')
+ return self.env['mail.message']
+
+ if not (model and res_id): # both value should be set or none should be set (record)
+ model = False
+ res_id = False
+
+ MailThread = self.env['mail.thread']
+ values = {
+ 'parent_id': parent_id,
+ 'model': self._name if self else False,
+ 'res_id': self.id if self else False,
+ 'message_type': 'user_notification',
+ 'subject': subject,
+ 'body': body,
+ 'author_id': author_id,
+ 'email_from': email_from,
+ 'partner_ids': partner_ids,
+ 'subtype_id': self.env['ir.model.data'].xmlid_to_res_id('mail.mt_note'),
+ 'is_internal': True,
+ 'record_name': False,
+ 'reply_to': MailThread._notify_get_reply_to(default=email_from, records=None)[False],
+ 'message_id': tools.generate_tracking_message_id('message-notify'),
+ }
+ values.update(msg_kwargs)
+ new_message = MailThread._message_create(values)
+ MailThread._notify_thread(new_message, values, **notif_kwargs)
+ return new_message
+
+ def _message_log(self, *, body='', author_id=None, email_from=None, subject=False, message_type='notification', **kwargs):
+ """ Shortcut allowing to post note on a document. It does not perform
+ any notification and pre-computes some values to have a short code
+ as optimized as possible. This method is private as it does not check
+ access rights and perform the message creation as sudo to speedup
+ the log process. This method should be called within methods where
+ access rights are already granted to avoid privilege escalation. """
+ self.ensure_one()
+ author_id, email_from = self._message_compute_author(author_id, email_from, raise_exception=False)
+
+ message_values = {
+ 'subject': subject,
+ 'body': body,
+ 'author_id': author_id,
+ 'email_from': email_from,
+ 'message_type': message_type,
+ 'model': kwargs.get('model', self._name),
+ 'res_id': self.ids[0] if self.ids else False,
+ 'subtype_id': self.env['ir.model.data'].xmlid_to_res_id('mail.mt_note'),
+ 'is_internal': True,
+ 'record_name': False,
+ 'reply_to': self.env['mail.thread']._notify_get_reply_to(default=email_from, records=None)[False],
+ 'message_id': tools.generate_tracking_message_id('message-notify'), # why? this is all but a notify
+ }
+ message_values.update(kwargs)
+ return self.sudo()._message_create(message_values)
+
+ def _message_log_batch(self, bodies, author_id=None, email_from=None, subject=False, message_type='notification'):
+ """ Shortcut allowing to post notes on a batch of documents. It achieve the
+ same purpose as _message_log, done in batch to speedup quick note log.
+
+ :param bodies: dict {record_id: body}
+ """
+ author_id, email_from = self._message_compute_author(author_id, email_from, raise_exception=False)
+
+ base_message_values = {
+ 'subject': subject,
+ 'author_id': author_id,
+ 'email_from': email_from,
+ 'message_type': message_type,
+ 'model': self._name,
+ 'subtype_id': self.env['ir.model.data'].xmlid_to_res_id('mail.mt_note'),
+ 'is_internal': True,
+ 'record_name': False,
+ 'reply_to': self.env['mail.thread']._notify_get_reply_to(default=email_from, records=None)[False],
+ 'message_id': tools.generate_tracking_message_id('message-notify'), # why? this is all but a notify
+ }
+ values_list = [dict(base_message_values,
+ res_id=record.id,
+ body=bodies.get(record.id, ''))
+ for record in self]
+ return self.sudo()._message_create(values_list)
+
+ def _message_compute_author(self, author_id=None, email_from=None, raise_exception=True):
+ """ Tool method computing author information for messages. Purpose is
+ to ensure maximum coherence between author / current user / email_from
+ when sending emails. """
+ if author_id is None:
+ if email_from:
+ author = self._mail_find_partner_from_emails([email_from])[0]
+ else:
+ author = self.env.user.partner_id
+ email_from = author.email_formatted
+ author_id = author.id
+
+ if email_from is None:
+ if author_id:
+ author = self.env['res.partner'].browse(author_id)
+ email_from = author.email_formatted
+
+ # superuser mode without author email -> probably public user; anyway we don't want to crash
+ if not email_from and not self.env.su and raise_exception:
+ raise exceptions.UserError(_("Unable to log message, please configure the sender's email address."))
+
+ return author_id, email_from
+
+ def _message_create(self, values_list):
+ if not isinstance(values_list, (list)):
+ values_list = [values_list]
+ create_values_list = []
+ for values in values_list:
+ create_values = dict(values)
+ # Avoid warnings about non-existing fields
+ for x in ('from', 'to', 'cc', 'canned_response_ids'):
+ create_values.pop(x, None)
+ create_values['partner_ids'] = [(4, pid) for pid in create_values.get('partner_ids', [])]
+ create_values['channel_ids'] = [(4, cid) for cid in create_values.get('channel_ids', [])]
+ create_values_list.append(create_values)
+ if 'default_child_ids' in self._context:
+ ctx = {key: val for key, val in self._context.items() if key != 'default_child_ids'}
+ self = self.with_context(ctx)
+ return self.env['mail.message'].create(create_values_list)
+
+ # ------------------------------------------------------
+ # NOTIFICATION API
+ # ------------------------------------------------------
+
+ def _notify_thread(self, message, msg_vals=False, notify_by_email=True, **kwargs):
+ """ Main notification method. This method basically does two things
+
+ * call ``_notify_compute_recipients`` that computes recipients to
+ notify based on message record or message creation values if given
+ (to optimize performance if we already have data computed);
+ * performs the notification process by calling the various notification
+ methods implemented;
+
+ This method cnn be overridden to intercept and postpone notification
+ mechanism like mail.channel moderation.
+
+ :param message: mail.message record to notify;
+ :param msg_vals: dictionary of values used to create the message. If given
+ it is used instead of accessing ``self`` to lessen query count in some
+ simple cases where no notification is actually required;
+
+ Kwargs allow to pass various parameters that are given to sub notification
+ methods. See those methods for more details about the additional parameters.
+ Parameters used for email-style notifications
+ """
+ msg_vals = msg_vals if msg_vals else {}
+ rdata = self._notify_compute_recipients(message, msg_vals)
+ if not rdata:
+ return False
+
+ message_values = {}
+ if rdata['channels']:
+ message_values['channel_ids'] = [(6, 0, [r['id'] for r in rdata['channels']])]
+
+ self._notify_record_by_inbox(message, rdata, msg_vals=msg_vals, **kwargs)
+ if notify_by_email:
+ self._notify_record_by_email(message, rdata, msg_vals=msg_vals, **kwargs)
+
+ return rdata
+
+ def _notify_record_by_inbox(self, message, recipients_data, msg_vals=False, **kwargs):
+ """ Notification method: inbox. Do two main things
+
+ * create an inbox notification for users;
+ * create channel / message link (channel_ids field of mail.message);
+ * send bus notifications;
+
+ TDE/XDO TODO: flag rdata directly, with for example r['notif'] = 'ocn_client' and r['needaction']=False
+ and correctly override notify_recipients
+ """
+ channel_ids = [r['id'] for r in recipients_data['channels']]
+ if channel_ids:
+ message.write({'channel_ids': [(6, 0, channel_ids)]})
+
+ inbox_pids = [r['id'] for r in recipients_data['partners'] if r['notif'] in('inbox','both')]
+ if inbox_pids:
+ notif_create_values = [{
+ 'mail_message_id': message.id,
+ 'res_partner_id': pid,
+ 'notification_type': 'inbox',
+ 'notification_status': 'sent',
+ } for pid in inbox_pids]
+ self.env['mail.notification'].sudo().create(notif_create_values)
+
+ bus_notifications = []
+ if inbox_pids or channel_ids:
+ message_format_values = False
+ if inbox_pids:
+ message_format_values = message.message_format()[0]
+ for partner_id in inbox_pids:
+ bus_notifications.append([(self._cr.dbname, 'ir.needaction', partner_id), dict(message_format_values)])
+ if channel_ids:
+ channels = self.env['mail.channel'].sudo().browse(channel_ids)
+ bus_notifications += channels._channel_message_notifications(message, message_format_values)
+
+ if bus_notifications:
+ self.env['bus.bus'].sudo().sendmany(bus_notifications)
+
+ def _notify_record_by_email(self, message, recipients_data, msg_vals=False,
+ model_description=False, mail_auto_delete=True, check_existing=False,
+ force_send=True, send_after_commit=True,
+ **kwargs):
+ """ Method to send email linked to notified messages.
+
+ :param message: mail.message record to notify;
+ :param recipients_data: see ``_notify_thread``;
+ :param msg_vals: see ``_notify_thread``;
+
+ :param model_description: model description used in email notification process
+ (computed if not given);
+ :param mail_auto_delete: delete notification emails once sent;
+ :param check_existing: check for existing notifications to update based on
+ mailed recipient, otherwise create new notifications;
+
+ :param force_send: send emails directly instead of using queue;
+ :param send_after_commit: if force_send, tells whether to send emails after
+ the transaction has been committed using a post-commit hook;
+ """
+ partners_data = [r for r in recipients_data['partners'] if r['notif'] in ('email','both')]
+ if not partners_data:
+ return True
+
+ model = msg_vals.get('model') if msg_vals else message.model
+ model_name = model_description or (self._fallback_lang().env['ir.model']._get(model).display_name if model else False) # one query for display name
+ recipients_groups_data = self._notify_classify_recipients(partners_data, model_name, msg_vals=msg_vals)
+
+ if not recipients_groups_data:
+ return True
+ force_send = self.env.context.get('mail_notify_force_send', force_send)
+
+ template_values = self._notify_prepare_template_context(message, msg_vals, model_description=model_description) # 10 queries
+
+ email_layout_xmlid = msg_vals.get('email_layout_xmlid') if msg_vals else message.email_layout_xmlid
+ template_xmlid = email_layout_xmlid if email_layout_xmlid else 'mail.message_notification_email'
+ try:
+ base_template = self.env.ref(template_xmlid, raise_if_not_found=True).with_context(lang=template_values['lang']) # 1 query
+ except ValueError:
+ _logger.warning('QWeb template %s not found when sending notification emails. Sending without layouting.' % (template_xmlid))
+ base_template = False
+
+ mail_subject = message.subject or (message.record_name and 'Re: %s' % message.record_name) # in cache, no queries
+ # prepare notification mail values
+ base_mail_values = {
+ 'mail_message_id': message.id,
+ 'mail_server_id': message.mail_server_id.id, # 2 query, check acces + read, may be useless, Falsy, when will it be used?
+ 'auto_delete': mail_auto_delete,
+ # due to ir.rule, user have no right to access parent message if message is not published
+ 'references': message.parent_id.sudo().message_id if message.parent_id else False,
+ 'subject': mail_subject,
+ }
+ base_mail_values = self._notify_by_email_add_values(base_mail_values)
+
+ # Clean the context to get rid of residual default_* keys that could cause issues during
+ # the mail.mail creation.
+ # Example: 'default_state' would refer to the default state of a previously created record
+ # from another model that in turns triggers an assignation notification that ends up here.
+ # This will lead to a traceback when trying to create a mail.mail with this state value that
+ # doesn't exist.
+ SafeMail = self.env['mail.mail'].sudo().with_context(clean_context(self._context))
+ SafeNotification = self.env['mail.notification'].sudo().with_context(clean_context(self._context))
+ emails = self.env['mail.mail'].sudo()
+
+ # loop on groups (customer, portal, user, ... + model specific like group_sale_salesman)
+ notif_create_values = []
+ recipients_max = 50
+ for recipients_group_data in recipients_groups_data:
+ # generate notification email content
+ recipients_ids = recipients_group_data.pop('recipients')
+ render_values = {**template_values, **recipients_group_data}
+ # {company, is_discussion, lang, message, model_description, record, record_name, signature, subtype, tracking_values, website_url}
+ # {actions, button_access, has_button_access, recipients}
+
+ if base_template:
+ mail_body = base_template._render(render_values, engine='ir.qweb', minimal_qcontext=True)
+ else:
+ mail_body = message.body
+ mail_body = self.env['mail.render.mixin']._replace_local_links(mail_body)
+
+ # create email
+ for recipients_ids_chunk in split_every(recipients_max, recipients_ids):
+ recipient_values = self._notify_email_recipient_values(recipients_ids_chunk)
+ email_to = recipient_values['email_to']
+ recipient_ids = recipient_values['recipient_ids']
+
+ create_values = {
+ 'body_html': mail_body,
+ 'subject': mail_subject,
+ 'recipient_ids': [(4, pid) for pid in recipient_ids],
+ }
+ if email_to:
+ create_values['email_to'] = email_to
+ create_values.update(base_mail_values) # mail_message_id, mail_server_id, auto_delete, references, headers
+ email = SafeMail.create(create_values)
+
+ if email and recipient_ids:
+ tocreate_recipient_ids = list(recipient_ids)
+ if check_existing:
+ existing_notifications = self.env['mail.notification'].sudo().search([
+ ('mail_message_id', '=', message.id),
+ ('notification_type', '=', 'email'),
+ ('res_partner_id', 'in', tocreate_recipient_ids)
+ ])
+ if existing_notifications:
+ tocreate_recipient_ids = [rid for rid in recipient_ids if rid not in existing_notifications.mapped('res_partner_id.id')]
+ existing_notifications.write({
+ 'notification_status': 'ready',
+ 'mail_id': email.id,
+ })
+ notif_create_values += [{
+ 'mail_message_id': message.id,
+ 'res_partner_id': recipient_id,
+ 'notification_type': 'email',
+ 'mail_id': email.id,
+ 'is_read': True, # discard Inbox notification
+ 'notification_status': 'ready',
+ } for recipient_id in tocreate_recipient_ids]
+ emails |= email
+
+ if notif_create_values:
+ SafeNotification.create(notif_create_values)
+
+ # NOTE:
+ # 1. for more than 50 followers, use the queue system
+ # 2. do not send emails immediately if the registry is not loaded,
+ # to prevent sending email during a simple update of the database
+ # using the command-line.
+ test_mode = getattr(threading.currentThread(), 'testing', False)
+ if force_send and len(emails) < recipients_max and (not self.pool._init or test_mode):
+ # unless asked specifically, send emails after the transaction to
+ # avoid side effects due to emails being sent while the transaction fails
+ if not test_mode and send_after_commit:
+ email_ids = emails.ids
+ dbname = self.env.cr.dbname
+ _context = self._context
+
+ @self.env.cr.postcommit.add
+ def send_notifications():
+ db_registry = registry(dbname)
+ with api.Environment.manage(), db_registry.cursor() as cr:
+ env = api.Environment(cr, SUPERUSER_ID, _context)
+ env['mail.mail'].browse(email_ids).send()
+ else:
+ emails.send()
+
+ return True
+
+ @api.model
+ def _notify_prepare_template_context(self, message, msg_vals, model_description=False, mail_auto_delete=True):
+ # compute send user and its related signature
+ signature = ''
+ user = self.env.user
+ author = message.env['res.partner'].browse(msg_vals.get('author_id')) if msg_vals else message.author_id
+ model = msg_vals.get('model') if msg_vals else message.model
+ add_sign = msg_vals.get('add_sign') if msg_vals else message.add_sign
+ subtype_id = msg_vals.get('subtype_id') if msg_vals else message.subtype_id.id
+ message_id = message.id
+ record_name = msg_vals.get('record_name') if msg_vals else message.record_name
+ author_user = user if user.partner_id == author else author.user_ids[0] if author and author.user_ids else False
+ # trying to use user (self.env.user) instead of browing user_ids if he is the author will give a sudo user,
+ # improving access performances and cache usage.
+ if author_user:
+ user = author_user
+ if add_sign:
+ signature = user.signature
+ else:
+ if add_sign:
+ signature = "-- %s
" % author.name
+
+ company = self.company_id.sudo() if self and 'company_id' in self else user.company_id
+ if company.website:
+ website_url = 'http://%s' % company.website if not company.website.lower().startswith(('http:', 'https:')) else company.website
+ else:
+ website_url = False
+
+ # Retrieve the language in which the template was rendered, in order to render the custom
+ # layout in the same language.
+ # TDE FIXME: this whole brol should be cleaned !
+ lang = self.env.context.get('lang')
+ if {'default_template_id', 'default_model', 'default_res_id'} <= self.env.context.keys():
+ template = self.env['mail.template'].browse(self.env.context['default_template_id'])
+ if template and template.lang:
+ lang = template._render_lang([self.env.context['default_res_id']])[self.env.context['default_res_id']]
+
+ if not model_description and model:
+ model_description = self.env['ir.model'].with_context(lang=lang)._get(model).display_name
+
+ tracking = []
+ if msg_vals.get('tracking_value_ids', True) if msg_vals else bool(self): # could be tracking
+ for tracking_value in self.env['mail.tracking.value'].sudo().search([('mail_message_id', '=', message.id)]):
+ groups = tracking_value.field_groups
+ if not groups or self.env.is_superuser() or self.user_has_groups(groups):
+ tracking.append((tracking_value.field_desc,
+ tracking_value.get_old_display_value()[0],
+ tracking_value.get_new_display_value()[0]))
+
+ is_discussion = subtype_id == self.env['ir.model.data'].xmlid_to_res_id('mail.mt_comment')
+
+ return {
+ 'message': message,
+ 'signature': signature,
+ 'website_url': website_url,
+ 'company': company,
+ 'model_description': model_description,
+ 'record': self,
+ 'record_name': record_name,
+ 'tracking_values': tracking,
+ 'is_discussion': is_discussion,
+ 'subtype': message.subtype_id,
+ 'lang': lang,
+ }
+
+ def _notify_by_email_add_values(self, base_mail_values):
+ """ Add model-specific values to the dictionary used to create the
+ notification email. Its base behavior is to compute model-specific
+ headers.
+
+ :param dict base_mail_values: base mail.mail values, holding message
+ to notify (mail_message_id and its fields), server, references, subject.
+ """
+ headers = self._notify_email_headers()
+ if headers:
+ base_mail_values['headers'] = headers
+ return base_mail_values
+
+ def _notify_compute_recipients(self, message, msg_vals):
+ """ Compute recipients to notify based on subtype and followers. This
+ method returns data structured as expected for ``_notify_recipients``. """
+ msg_sudo = message.sudo()
+ # get values from msg_vals or from message if msg_vals doen't exists
+ pids = msg_vals.get('partner_ids', []) if msg_vals else msg_sudo.partner_ids.ids
+ cids = msg_vals.get('channel_ids', []) if msg_vals else msg_sudo.channel_ids.ids
+ message_type = msg_vals.get('message_type') if msg_vals else msg_sudo.message_type
+ subtype_id = msg_vals.get('subtype_id') if msg_vals else msg_sudo.subtype_id.id
+ # is it possible to have record but no subtype_id ?
+ recipient_data = {
+ 'partners': [],
+ 'channels': [],
+ }
+ res = self.env['mail.followers']._get_recipient_data(self, message_type, subtype_id, pids, cids)
+ if not res:
+ return recipient_data
+
+ author_id = msg_vals.get('author_id') or message.author_id.id
+ for pid, cid, active, pshare, ctype, notif, groups in res:
+ if pid and pid == author_id and not self.env.context.get('mail_notify_author'): # do not notify the author of its own messages
+ continue
+ if pid:
+ if active is False:
+ continue
+ pdata = {'id': pid, 'active': active, 'share': pshare, 'groups': groups or []}
+ if notif == 'inbox':
+ recipient_data['partners'].append(dict(pdata, notif=notif, type='user'))
+ elif not pshare and notif: # has an user and is not shared, is therefore user
+ recipient_data['partners'].append(dict(pdata, notif=notif, type='user'))
+ elif pshare and notif: # has an user but is shared, is therefore portal
+ recipient_data['partners'].append(dict(pdata, notif=notif, type='portal'))
+ else: # has no user, is therefore customer
+ recipient_data['partners'].append(dict(pdata, notif=notif if notif else 'email', type='customer'))
+ elif cid:
+ recipient_data['channels'].append({'id': cid, 'notif': notif, 'type': ctype})
+
+ # add partner ids in email channels
+ email_cids = [r['id'] for r in recipient_data['channels'] if r['notif'] == 'email']
+ if email_cids:
+ # we are doing a similar search in ocn_client
+ # Could be interesting to make everything in a single query.
+ # ocn_client: (searching all partners linked to channels of type chat).
+ # here : (searching all partners linked to channels with notif email if email is not the author one)
+ # TDE FIXME: use email_sanitized
+ email_from = msg_vals.get('email_from') or message.email_from
+ email_from = self.env['res.partner']._parse_partner_name(email_from)[1]
+ exept_partner = [r['id'] for r in recipient_data['partners']]
+ if author_id:
+ exept_partner.append(author_id)
+
+ sql_query = """ select distinct on (p.id) p.id from res_partner p
+ left join mail_channel_partner mcp on p.id = mcp.partner_id
+ left join mail_channel c on c.id = mcp.channel_id
+ left join res_users u on p.id = u.partner_id
+ where (u.notification_type != 'inbox' or u.id is null)
+ and (p.email != ANY(%s) or p.email is null)
+ and c.id = ANY(%s)
+ and p.id != ANY(%s)"""
+
+ self.env.cr.execute(sql_query, (([email_from], ), (email_cids, ), (exept_partner, )))
+ for partner_id in self._cr.fetchall():
+ # ocn_client: will add partners to recipient recipient_data. more ocn notifications. We neeed to filter them maybe
+ recipient_data['partners'].append({'id': partner_id[0], 'share': True, 'active': True, 'notif': 'email', 'type': 'channel_email', 'groups': []})
+
+ return recipient_data
+
+ @api.model
+ def _notify_encode_link(self, base_link, params):
+ secret = self.env['ir.config_parameter'].sudo().get_param('database.secret')
+ token = '%s?%s' % (base_link, ' '.join('%s=%s' % (key, params[key]) for key in sorted(params)))
+ hm = hmac.new(secret.encode('utf-8'), token.encode('utf-8'), hashlib.sha1).hexdigest()
+ return hm
+
+ def _notify_get_action_link(self, link_type, **kwargs):
+ """ Prepare link to an action: view document, follow document, ... """
+ params = {
+ 'model': kwargs.get('model', self._name),
+ 'res_id': kwargs.get('res_id', self.ids and self.ids[0] or False),
+ }
+ # whitelist accepted parameters: action (deprecated), token (assign), access_token
+ # (view), auth_signup_token and auth_login (for auth_signup support)
+ params.update(dict(
+ (key, value)
+ for key, value in kwargs.items()
+ if key in ('action', 'token', 'access_token', 'auth_signup_token', 'auth_login')
+ ))
+
+ if link_type in ['view', 'assign', 'follow', 'unfollow']:
+ base_link = '/mail/%s' % link_type
+ elif link_type == 'controller':
+ controller = kwargs.get('controller')
+ params.pop('model')
+ base_link = '%s' % controller
+ else:
+ return ''
+
+ if link_type not in ['view']:
+ token = self._notify_encode_link(base_link, params)
+ params['token'] = token
+
+ link = '%s?%s' % (base_link, urls.url_encode(params))
+ if self:
+ link = self[0].get_base_url() + link
+
+ return link
+
+ def _notify_get_groups(self, msg_vals=None):
+ """ Return groups used to classify recipients of a notification email.
+ Groups is a list of tuple containing of form (group_name, group_func,
+ group_data) where
+ * group_name is an identifier used only to be able to override and manipulate
+ groups. Default groups are user (recipients linked to an employee user),
+ portal (recipients linked to a portal user) and customer (recipients not
+ linked to any user). An example of override use would be to add a group
+ linked to a res.groups like Hr Officers to set specific action buttons to
+ them.
+ * group_func is a function pointer taking a partner record as parameter. This
+ method will be applied on recipients to know whether they belong to a given
+ group or not. Only first matching group is kept. Evaluation order is the
+ list order.
+ * group_data is a dict containing parameters for the notification email
+ * has_button_access: whether to display Access in email. True
+ by default for new groups, False for portal / customer.
+ * button_access: dict with url and title of the button
+ * actions: list of action buttons to display in the notification email.
+ Each action is a dict containing url and title of the button.
+ Groups has a default value that you can find in mail_thread
+ ``_notify_classify_recipients`` method.
+ """
+ return [
+ (
+ 'user',
+ lambda pdata: pdata['type'] == 'user',
+ {}
+ ), (
+ 'portal',
+ lambda pdata: pdata['type'] == 'portal',
+ {'has_button_access': False}
+ ), (
+ 'customer',
+ lambda pdata: True,
+ {'has_button_access': False}
+ )
+ ]
+
+ def _notify_classify_recipients(self, recipient_data, model_name, msg_vals=None):
+ """ Classify recipients to be notified of a message in groups to have
+ specific rendering depending on their group. For example users could
+ have access to buttons customers should not have in their emails.
+ Module-specific grouping should be done by overriding ``_notify_get_groups``
+ method defined here-under.
+ :param recipient_data:todo xdo UPDATE ME
+ return example:
+ [{
+ 'actions': [],
+ 'button_access': {'title': 'View Simple Chatter Model',
+ 'url': '/mail/view?model=mail.test.simple&res_id=1497'},
+ 'has_button_access': False,
+ 'recipients': [11]
+ },
+ {
+ 'actions': [],
+ 'button_access': {'title': 'View Simple Chatter Model',
+ 'url': '/mail/view?model=mail.test.simple&res_id=1497'},
+ 'has_button_access': False,
+ 'recipients': [4, 5, 6]
+ },
+ {
+ 'actions': [],
+ 'button_access': {'title': 'View Simple Chatter Model',
+ 'url': '/mail/view?model=mail.test.simple&res_id=1497'},
+ 'has_button_access': True,
+ 'recipients': [10, 11, 12]
+ }]
+ only return groups with recipients
+ """
+ # keep a local copy of msg_vals as it may be modified to include more information about groups or links
+ local_msg_vals = dict(msg_vals) if msg_vals else {}
+ groups = self._notify_get_groups(msg_vals=local_msg_vals)
+ access_link = self._notify_get_action_link('view', **local_msg_vals)
+
+ if model_name:
+ view_title = _('View %s', model_name)
+ else:
+ view_title = _('View')
+
+ # fill group_data with default_values if they are not complete
+ for group_name, group_func, group_data in groups:
+ group_data.setdefault('notification_group_name', group_name)
+ group_data.setdefault('notification_is_customer', False)
+ group_data.setdefault('has_button_access', True)
+ group_button_access = group_data.setdefault('button_access', {})
+ group_button_access.setdefault('url', access_link)
+ group_button_access.setdefault('title', view_title)
+ group_data.setdefault('actions', list())
+ group_data.setdefault('recipients', list())
+
+ # classify recipients in each group
+ for recipient in recipient_data:
+ for group_name, group_func, group_data in groups:
+ if group_func(recipient):
+ group_data['recipients'].append(recipient['id'])
+ break
+
+ result = []
+ for group_name, group_method, group_data in groups:
+ if group_data['recipients']:
+ result.append(group_data)
+
+ return result
+
+ @api.model
+ def _notify_get_reply_to_on_records(self, default=None, records=None, company=None, doc_names=None):
+ """ Moved to ``BaseModel._notify_get_reply_to()`` """
+ records = records if records else self
+ return records._notify_get_reply_to(default=default, company=company, doc_names=doc_names)
+
+ def _notify_email_recipient_values(self, recipient_ids):
+ """ Format email notification recipient values to store on the notification
+ mail.mail. Basic method just set the recipient partners as mail_mail
+ recipients. Override to generate other mail values like email_to or
+ email_cc.
+ :param recipient_ids: res.partner recordset to notify
+ """
+ return {
+ 'email_to': False,
+ 'recipient_ids': recipient_ids,
+ }
+
+ # ------------------------------------------------------
+ # FOLLOWERS API
+ # ------------------------------------------------------
+
+ def message_subscribe(self, partner_ids=None, channel_ids=None, subtype_ids=None):
+ """ Main public API to add followers to a record set. Its main purpose is
+ to perform access rights checks before calling ``_message_subscribe``. """
+ if not self or (not partner_ids and not channel_ids):
+ return True
+
+ partner_ids = partner_ids or []
+ channel_ids = channel_ids or []
+ adding_current = set(partner_ids) == set([self.env.user.partner_id.id])
+ customer_ids = [] if adding_current else None
+
+ if not channel_ids and partner_ids and adding_current:
+ try:
+ self.check_access_rights('read')
+ self.check_access_rule('read')
+ except exceptions.AccessError:
+ return False
+ else:
+ self.check_access_rights('write')
+ self.check_access_rule('write')
+
+ # filter inactive and private addresses
+ if partner_ids and not adding_current:
+ partner_ids = self.env['res.partner'].sudo().search([('id', 'in', partner_ids), ('active', '=', True), ('type', '!=', 'private')]).ids
+
+ return self._message_subscribe(partner_ids, channel_ids, subtype_ids, customer_ids=customer_ids)
+
+ def _message_subscribe(self, partner_ids=None, channel_ids=None, subtype_ids=None, customer_ids=None):
+ """ Main private API to add followers to a record set. This method adds
+ partners and channels, given their IDs, as followers of all records
+ contained in the record set.
+
+ If subtypes are given existing followers are erased with new subtypes.
+ If default one have to be computed only missing followers will be added
+ with default subtypes matching the record set model.
+
+ This private method does not specifically check for access right. Use
+ ``message_subscribe`` public API when not sure about access rights.
+
+ :param customer_ids: see ``_insert_followers`` """
+ if not self:
+ return True
+ curframe = inspect.currentframe()
+ calframe = inspect.getouterframes(curframe, 2)
+ print('caller name:', calframe)
+
+ if not subtype_ids:
+ self.env['mail.followers']._insert_followers(
+ self._name, self.ids, partner_ids, None, channel_ids, None,
+ customer_ids=customer_ids, check_existing=True, existing_policy='skip')
+ else:
+ self.env['mail.followers']._insert_followers(
+ self._name, self.ids,
+ partner_ids, dict((pid, subtype_ids) for pid in partner_ids),
+ channel_ids, dict((cid, subtype_ids) for cid in channel_ids),
+ customer_ids=customer_ids, check_existing=True, existing_policy='replace')
+
+ return True
+
+ def message_unsubscribe(self, partner_ids=None, channel_ids=None):
+ """ Remove partners from the records followers. """
+ # not necessary for computation, but saves an access right check
+ if not partner_ids and not channel_ids:
+ return True
+ user_pid = self.env.user.partner_id.id
+ if not channel_ids and set(partner_ids) == set([user_pid]):
+ self.check_access_rights('read')
+ self.check_access_rule('read')
+ else:
+ self.check_access_rights('write')
+ self.check_access_rule('write')
+ self.env['mail.followers'].sudo().search([
+ ('res_model', '=', self._name),
+ ('res_id', 'in', self.ids),
+ '|',
+ ('partner_id', 'in', partner_ids or []),
+ ('channel_id', 'in', channel_ids or [])
+ ]).unlink()
+
+ def _message_auto_subscribe_followers(self, updated_values, default_subtype_ids):
+ """ Optional method to override in addons inheriting from mail.thread.
+ Return a list tuples containing (
+ partner ID,
+ subtype IDs (or False if model-based default subtypes),
+ QWeb template XML ID for notification (or False is no specific
+ notification is required),
+ ), aka partners and their subtype and possible notification to send
+ using the auto subscription mechanism linked to updated values.
+
+ Default value of this method is to return the new responsible of
+ documents. This is done using relational fields linking to res.users
+ with track_visibility set. Since OpenERP v7 it is considered as being
+ responsible for the document and therefore standard behavior is to
+ subscribe the user and send him a notification.
+
+ Override this method to change that behavior and/or to add people to
+ notify, using possible custom notification.
+
+ :param updated_values: see ``_message_auto_subscribe``
+ :param default_subtype_ids: coming from ``_get_auto_subscription_subtypes``
+ """
+ fnames = []
+ field = self._fields.get('user_id')
+ user_id = updated_values.get('user_id')
+ if field and user_id and field.comodel_name == 'res.users' and (getattr(field, 'track_visibility', False) or getattr(field, 'tracking', False)):
+ user = self.env['res.users'].sudo().browse(user_id)
+ try: # avoid to make an exists, lets be optimistic and try to read it.
+ if user.active:
+ return [(user.partner_id.id, default_subtype_ids, 'mail.message_user_assigned' if user != self.env.user else False)]
+ except:
+ pass
+ return []
+
+ def _message_auto_subscribe_notify(self, partner_ids, template):
+ """ Notify new followers, using a template to render the content of the
+ notification message. Notifications pushed are done using the standard
+ notification mechanism in mail.thread. It is either inbox either email
+ depending on the partner state: no user (email, customer), share user
+ (email, customer) or classic user (notification_type)
+
+ :param partner_ids: IDs of partner to notify;
+ :param template: XML ID of template used for the notification;
+ """
+ if not self or self.env.context.get('mail_auto_subscribe_no_notify'):
+ return
+ if not self.env.registry.ready: # Don't send notification during install
+ return
+
+ view = self.env['ir.ui.view'].browse(self.env['ir.model.data'].xmlid_to_res_id(template))
+
+ for record in self:
+ model_description = self.env['ir.model']._get(record._name).display_name
+ values = {
+ 'object': record,
+ 'model_description': model_description,
+ 'access_link': record._notify_get_action_link('view'),
+ }
+ assignation_msg = view._render(values, engine='ir.qweb', minimal_qcontext=True)
+ assignation_msg = self.env['mail.render.mixin']._replace_local_links(assignation_msg)
+ record.message_notify(
+ subject=_('You have been assigned to %s', record.display_name),
+ body=assignation_msg,
+ partner_ids=partner_ids,
+ record_name=record.display_name,
+ email_layout_xmlid='mail.mail_notification_light',
+ model_description=model_description,
+ )
+
+ def _message_auto_subscribe(self, updated_values, followers_existing_policy='skip'):
+ """ Handle auto subscription. Auto subscription is done based on two
+ main mechanisms
+
+ * using subtypes parent relationship. For example following a parent record
+ (i.e. project) with subtypes linked to child records (i.e. task). See
+ mail.message.subtype ``_get_auto_subscription_subtypes``;
+ * calling _message_auto_subscribe_notify that returns a list of partner
+ to subscribe, as well as data about the subtypes and notification
+ to send. Base behavior is to subscribe responsible and notify them;
+
+ Adding application-specific auto subscription should be done by overriding
+ ``_message_auto_subscribe_followers``. It should return structured data
+ for new partner to subscribe, with subtypes and eventual notification
+ to perform. See that method for more details.
+
+ :param updated_values: values modifying the record trigerring auto subscription
+ """
+ curframe = inspect.currentframe()
+ calframe = inspect.getouterframes(curframe, 2)
+ print('caller name:', calframe)
+ if not self:
+ return True
+
+ new_partners, new_channels = dict(), dict()
+
+ # return data related to auto subscription based on subtype matching (aka:
+ # default task subtypes or subtypes from project triggering task subtypes)
+ updated_relation = dict()
+ child_ids, def_ids, all_int_ids, parent, relation = self.env['mail.message.subtype']._get_auto_subscription_subtypes(self._name)
+
+ # check effectively modified relation field
+ for res_model, fnames in relation.items():
+ for field in (fname for fname in fnames if updated_values.get(fname)):
+ updated_relation.setdefault(res_model, set()).add(field)
+ udpated_fields = [fname for fnames in updated_relation.values() for fname in fnames if updated_values.get(fname)]
+
+ if udpated_fields:
+ # fetch "parent" subscription data (aka: subtypes on project to propagate on task)
+ doc_data = [(model, [updated_values[fname] for fname in fnames]) for model, fnames in updated_relation.items()]
+ res = self.env['mail.followers']._get_subscription_data(doc_data, None, None, include_pshare=True, include_active=True)
+ for fid, rid, pid, cid, subtype_ids, pshare, active in res:
+ # use project.task_new -> task.new link
+ sids = [parent[sid] for sid in subtype_ids if parent.get(sid)]
+ # add checked subtypes matching model_name
+ sids += [sid for sid in subtype_ids if sid not in parent and sid in child_ids]
+ if pid and active: # auto subscribe only active partners
+ if pshare: # remove internal subtypes for customers
+ new_partners[pid] = set(sids) - set(all_int_ids)
+ else:
+ new_partners[pid] = set(sids)
+ if cid: # never subscribe channels to internal subtypes
+ new_channels[cid] = set(sids) - set(all_int_ids)
+
+ notify_data = dict()
+ res = self._message_auto_subscribe_followers(updated_values, def_ids)
+ for pid, sids, template in res:
+ new_partners.setdefault(pid, sids)
+ if template:
+ partner = self.env['res.partner'].browse(pid)
+ lang = partner.lang if partner else None
+ notify_data.setdefault((template, lang), list()).append(pid)
+
+ self.env['mail.followers']._insert_followers(
+ self._name, self.ids,
+ list(new_partners), new_partners,
+ list(new_channels), new_channels,
+ check_existing=True, existing_policy=followers_existing_policy)
+
+ # notify people from auto subscription, for example like assignation
+ for (template, lang), pids in notify_data.items():
+ self.with_context(lang=lang)._message_auto_subscribe_notify(pids, template)
+
+ return True
+
+ # ------------------------------------------------------
+ # CONTROLLERS
+ # ------------------------------------------------------
+
+ def _get_mail_redirect_suggested_company(self):
+ """ Return the suggested company to be set on the context
+ in case of a mail redirection to the record. To avoid multi
+ company issues when clicking on a link sent by email, this
+ could be called to try setting the most suited company on
+ the allowed_company_ids in the context. This method can be
+ overridden, for example on the hr.leave model, where the
+ most suited company is the company of the leave type, as
+ specified by the ir.rule.
+ """
+ if 'company_id' in self:
+ return self.company_id
+ return False
\ No newline at end of file
diff --git a/inbox_notif_email/security/ir.model.access.csv b/inbox_notif_email/security/ir.model.access.csv
new file mode 100644
index 0000000..e95836d
--- /dev/null
+++ b/inbox_notif_email/security/ir.model.access.csv
@@ -0,0 +1,2 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+access_inbox_notif_email_inbox_notif_email,inbox_notif_email.inbox_notif_email,model_inbox_notif_email_inbox_notif_email,base.group_user,1,1,1,1
\ No newline at end of file
diff --git a/inbox_notif_email/static/description/banner.PNG b/inbox_notif_email/static/description/banner.PNG
new file mode 100644
index 0000000..98cab95
Binary files /dev/null and b/inbox_notif_email/static/description/banner.PNG differ
diff --git a/inbox_notif_email/static/description/icon.png b/inbox_notif_email/static/description/icon.png
new file mode 100644
index 0000000..0deb667
Binary files /dev/null and b/inbox_notif_email/static/description/icon.png differ
diff --git a/inbox_notif_email/static/description/image1.png b/inbox_notif_email/static/description/image1.png
new file mode 100644
index 0000000..98cab95
Binary files /dev/null and b/inbox_notif_email/static/description/image1.png differ
diff --git a/inbox_notif_email/static/description/image10.png b/inbox_notif_email/static/description/image10.png
new file mode 100644
index 0000000..a614bd5
Binary files /dev/null and b/inbox_notif_email/static/description/image10.png differ
diff --git a/inbox_notif_email/static/description/image2.png b/inbox_notif_email/static/description/image2.png
new file mode 100644
index 0000000..9ad2bb0
Binary files /dev/null and b/inbox_notif_email/static/description/image2.png differ
diff --git a/inbox_notif_email/static/description/image3.png b/inbox_notif_email/static/description/image3.png
new file mode 100644
index 0000000..0e9e470
Binary files /dev/null and b/inbox_notif_email/static/description/image3.png differ
diff --git a/inbox_notif_email/static/description/image4.png b/inbox_notif_email/static/description/image4.png
new file mode 100644
index 0000000..18b074a
Binary files /dev/null and b/inbox_notif_email/static/description/image4.png differ
diff --git a/inbox_notif_email/static/description/image5.png b/inbox_notif_email/static/description/image5.png
new file mode 100644
index 0000000..777d1f8
Binary files /dev/null and b/inbox_notif_email/static/description/image5.png differ
diff --git a/inbox_notif_email/static/description/image6.png b/inbox_notif_email/static/description/image6.png
new file mode 100644
index 0000000..42ff122
Binary files /dev/null and b/inbox_notif_email/static/description/image6.png differ
diff --git a/inbox_notif_email/static/description/image7.png b/inbox_notif_email/static/description/image7.png
new file mode 100644
index 0000000..098f48e
Binary files /dev/null and b/inbox_notif_email/static/description/image7.png differ
diff --git a/inbox_notif_email/static/description/image8.png b/inbox_notif_email/static/description/image8.png
new file mode 100644
index 0000000..ee12616
Binary files /dev/null and b/inbox_notif_email/static/description/image8.png differ
diff --git a/inbox_notif_email/static/description/image9.png b/inbox_notif_email/static/description/image9.png
new file mode 100644
index 0000000..0ffa976
Binary files /dev/null and b/inbox_notif_email/static/description/image9.png differ
diff --git a/inbox_notif_email/static/description/index.html b/inbox_notif_email/static/description/index.html
new file mode 100644
index 0000000..f0db026
--- /dev/null
+++ b/inbox_notif_email/static/description/index.html
@@ -0,0 +1,93 @@
+
+
+
+
+
+
+
+
+
+ Supported :
+
+
+
+
+
+ Enterprise
+
+
+
+
+
+ Community
+
+
+
+
+
+ Odoo.sh
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ odoo notification and email notification both
+
+
+ The Problem
+By default, Odoo provides two options for Notification Management:
+
+Handle by Emails: notifications are sent to the users' email. This is the default option for new user creation
+Handle in Odoo: notifications appear in the users' Odoo Inbox but no email sent to the users
+This module does the following
+Handle by both now offers both inbox and email notifications
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Please contact mdadnanusmani@gmail.com for any query
+
+
diff --git a/inbox_notif_email/views/templates.xml b/inbox_notif_email/views/templates.xml
new file mode 100644
index 0000000..cea6b39
--- /dev/null
+++ b/inbox_notif_email/views/templates.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/inbox_notif_email/views/views.xml b/inbox_notif_email/views/views.xml
new file mode 100644
index 0000000..61b3ad7
--- /dev/null
+++ b/inbox_notif_email/views/views.xml
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/odex30_base/branch/__init__.py b/odex30_base/branch/__init__.py
index 129043b..55a846b 100644
--- a/odex30_base/branch/__init__.py
+++ b/odex30_base/branch/__init__.py
@@ -4,6 +4,3 @@ from . import models
from . import reports
from . import wizard
from . import controllers
-from .hooks import post_init_hook
-
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/odex30_base/branch/__manifest__.py b/odex30_base/branch/__manifest__.py
index 913289e..ef7b256 100644
--- a/odex30_base/branch/__manifest__.py
+++ b/odex30_base/branch/__manifest__.py
@@ -14,78 +14,7 @@
unit All Accounting reports Unit Accounting filter branch unit for warehouse branch unit for sale stock branch unit for location
Unit Operation for POS Unit Operation for Sales Unit operation for Purchase Unit operation for all Unit operation for Accounting Unit Operation for invoicing Unit operation for Payment order Unit operation for point of sales Unit operation for voucher Unit operation for All Accounting reports Unit operation Accounting filter.
Branch Operation for POS Branch Operation for Sales Branch operation for Purchase Branch operation for all Branch operation for Accounting Branch Operation for invoicing Branch operation for Payment order Branch operation for point of sales Branch operation for voucher Branch operation for All Accounting reports Branch operation Accounting filter.
- Odoo pos multi branch POS odoo point of sale multi branch point of sales
- odoo point of sales multi branch on POS
- Odoo pos multiple branch POS odoo point of sale multiple branch point of sales
- odoo point of sales multiple branch on POS
- Odoo pos multiple-branch POS odoo point of sale multiple-branch point of sales
- odoo point of sales multiple-branch on POS
- odoo Multiple Unit operation management for single company Multiple Branch management for single company
- odoo multiple operation for single company. branching company in odoo multiple store multiple company in odoo
- odoo Branch for POS Branch for Sales Branch for Purchase Branch for all Branch for Accounting Branch for invoicing Branch for Payment order Branch for point of sales Branch for voucher
- odoo Branch for All Accounting reports Branch Accounting filter Branch for warehouse branch for sale stock branch for location
- odoo Unit for POS Unit for Sales Unit for Purchase Unit for all Unit for Accounting Unit for invoicing Unit for Payment order
- odoo Unit for point of sales Unit for voucher Unit for All Accounting reports Unit Accounting filter
- odoo branch unit for warehouse branch unit for sale stock branch unit for location
- odoo Unit Operation for POS Unit Operation for Sales Unit operation for Purchase Unit operation for all Unit operation for Accounting
- odoo Unit Operation for invoicing Unit operation for Payment order Unit operation for point of sales Unit operation for voucher Unit operation for All Accounting reports
- odoo Unit operation Accounting filter Branch Operation for POS Branch Operation for Sales
- odoo Branch operation for Purchase Branch operation for all Branch operation for Accounting Branch Operation for invoicing
- odoo Branch operation for Payment order Branch operation for point of sales Branch operation for voucher Branch operation for All Accounting reports Branch operation Accounting filter.
- odoo branch helpdesk and support branch support and helpdesk
- odoo helpdesk branch helpdesk unit helpdek multiple unit helpdesk operation unit
- odoo branch crm odoo crm branch crm operating unit crm unit operation management crm multiple unit operating unit crm
- odoo branch Subscription branch contract Subscription branch management
- odoo contract branch management operating unit Subscription operating unit contract
- odoo Subscription unit management contract unit management Subscription operating unit management
- odoo contract operating unit management operating unit for company multi branch management
- odoo multi branch application multi operation unit application multi branch odoo multi branch
- odoo all in one multi branch application multi branch unit operation multi unit operation branch management
- odoo multi branches management application multi operation management operating Unit for POS operating Unit for Sales
- odoo operating Units for Purchase operating Unit for all operating Unit for Accounting operating Unit for invoicing
- odoo operating Unit for Payment order operating Unit for point of sales operating Unit for voucher operating Unit for All Accounting reports operating Unit Accounting filter.
- odoo Operating unit for picking operating unit for warehouse operating unit for sale stock operating unit for location
-odoo operating-Unit Operation for POS operating-Unit Operation for Sales operating-Unit operation for Purchase operating-Unit operation for all
-odoo operating-Unit operation for Accounting operating-Unit Operation for invoicing operating-Unit operation for Payment order operating-Unit operation for point of sales
-odoo operating-Unit operation for voucher operating-Unit operation for All Accounting reports operating-Unit operation Accounting filter.
-odoo multi branches management odoo branches management odoo multiple branches management on odoo branchs mananegement
-odoo many branches for single company odoo
-
- branch helpdesk and support
- branch support and helpdesk
- helpdesk branch
- helpdesk unit
- helpdek multiple unit
- helpdesk operation unit
- branch crm
- MultiBranch
- multi company
- crm branch
- crm operating unit
- crm unit operation management
- crm multiple unit
- operating unit crm
- branch Subscription
- branch contract
- Subscription branch management
- contract branch management
- operating unit Subscription
- operating unit contract
- Subscription unit management
- contract unit management
- Subscription operating unit management
- contract operating unit management
-
- operating unit for company.
- multi branch management
- multi branch application
- multi operation unit application multi branch odoo multi branch
- all in one multi branch application multi branch unit operation multi unit operation branch management
- odoo multi branches management application multi operation management
-
-operating Unit for POS,operating Unit for Sales,operating Unit for Purchase,operating Unit for all,operating Unit for Accounting,operating Unit for invoicing,operating Unit for Payment order,operating Unit for point of sales,operating Unit for voucher,operating Unit for All Accounting reports,operating Unit Accounting filter. Operating unit for picking, operating unit for warehouse, operating unit for sale stock, operating unit for location
-operating-Unit Operation for POS,operating-Unit Operation for Sales,operating-Unit operation for Purchase,operating-Unit operation for all, operating-Unit operation for Accounting,operating-Unit Operation for invoicing,operating-Unit operation for Payment order,operating-Unit operation for point of sales,operating-Unit operation for voucher,operating-Unit operation for All Accounting reports,operating-Unit operation Accounting filter.
- """,
+ """,
'author': 'BrowseInfo',
'website': 'https://www.browseinfo.in',
"price": 149.00,
@@ -93,37 +22,31 @@ operating-Unit Operation for POS,operating-Unit Operation for Sales,operating-Un
'depends': ['base', 'sale_management', 'purchase', 'stock', 'account', 'purchase_stock','web'],
'data': [
'security/branch_security.xml',
- 'security/multi_branch.xml',
'security/ir.model.access.csv',
+ 'views/account_bank_statement.xml',
+ 'views/account_move.xml',
+ 'views/account_payment.xml',
+ 'views/product.xml',
+ 'views/purchase_order.xml',
'views/res_branch_view.xml',
- 'views/inherited_res_users.xml',
- 'views/inherited_sale_order.xml',
- 'views/inherited_stock_picking.xml',
- 'views/inherited_stock_move.xml',
- 'views/inherited_account_invoice.xml',
- 'views/inherited_purchase_order.xml',
- 'views/inherited_stock_warehouse.xml',
- 'views/inherited_stock_location.xml',
- 'views/inherited_account_bank_statement.xml',
- 'wizard/inherited_account_payment.xml',
- 'views/inherited_stock_inventory.xml',
- 'views/inherited_product.xml',
- 'views/inherited_partner.xml',
- 'views/branch_template.xml',
+ 'views/res_partner.xml',
+ 'views/res_users.xml',
+ 'views/sale_order.xml',
+ 'views/stock_location.xml',
+ 'views/stock_move.xml',
+ 'views/stock_picking_type.xml',
+ 'views/stock_picking.xml',
+ 'views/stock_warehouse.xml',
],
- 'assets': {
- 'web.assets_backend': [
- 'branch/static/src/js/session.js',
- 'branch/static/src/js/abstract_web_client.js',
- 'branch/static/src/js/default_branch.js',
- 'branch/static/src/xml/branch.xml',
- ],
- },
+
+ # 'assets': {
+ # 'web.assets_backend': [
+ # 'branch/static/src/**/*',
+ # ]
+ # },
'installable': True,
'auto_install': False,
'live_test_url':'https://youtu.be/hi1b8kH5Z94',
"images":['static/description/Banner.png'],
- 'post_init_hook': 'post_init_hook',
}
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/odex30_base/branch/controllers/main.py b/odex30_base/branch/controllers/main.py
index 97f169e..6ac60bd 100644
--- a/odex30_base/branch/controllers/main.py
+++ b/odex30_base/branch/controllers/main.py
@@ -2,7 +2,6 @@
# Part of BrowseInfo. See LICENSE file for full copyright and licensing details.
from odoo import http, _
-from odoo.addons.portal.controllers.portal import CustomerPortal, pager as portal_pager
from odoo.http import request
class SetBranch(http.Controller):
@@ -12,5 +11,3 @@ class SetBranch(http.Controller):
user_id = request.env['res.users'].sudo().search([('id','=',request.env.user.id)])
user_id.branch_id = BranchID
return
-
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
diff --git a/odex30_base/branch/hooks.py b/odex30_base/branch/hooks.py
deleted file mode 100644
index d26afc8..0000000
--- a/odex30_base/branch/hooks.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# -*- encoding: utf-8 -*-
-# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-
-from odoo import SUPERUSER_ID
-from odoo import api
-
-
-def post_init_hook(cr, registry):
- """
- website menu hide
- """
- env = api.Environment(cr, SUPERUSER_ID, {})
- cr.execute("""
- update ir_model_data set noupdate=False where
- model ='ir.rule' """)
diff --git a/odex30_base/branch/models/__init__.py b/odex30_base/branch/models/__init__.py
index 67886b1..de5e069 100644
--- a/odex30_base/branch/models/__init__.py
+++ b/odex30_base/branch/models/__init__.py
@@ -1,20 +1,18 @@
# Part of BrowseInfo. See LICENSE file for full copyright and licensing details.
from . import branch
-from . import inherited_res_users
-from . import inherited_sale_order
-from . import inherited_stock_move
-from . import inherited_stock_picking
-from . import inherited_account_move
-from . import inherited_account_payment
-from . import inherited_purchase_order
-from . import inherited_stock_warehouse
-from . import inherited_stock_location
-from . import inherited_account_bank_statement
-from . import inherited_account_bank_statement_line
-from . import inherited_stock_inventory
-from . import inherited_customer
-from . import inherited_product
+from . import res_users
+from . import sale_order
+from . import stock_move
+from . import stock_picking
+from . import account_move
+from . import account_payment
+from . import purchase_order
+from . import stock_picking_type
+from . import stock_location
+from . import account_bank_statement
+from . import account_bank_statement_line
+from . import res_partner
+from . import product
from . import ir_http
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/odex30_base/branch/models/inherited_account_bank_statement.py b/odex30_base/branch/models/account_bank_statement.py
similarity index 53%
rename from odex30_base/branch/models/inherited_account_bank_statement.py
rename to odex30_base/branch/models/account_bank_statement.py
index 952f92e..a7f2aef 100644
--- a/odex30_base/branch/models/inherited_account_bank_statement.py
+++ b/odex30_base/branch/models/account_bank_statement.py
@@ -7,27 +7,40 @@ import time
class AccountBankStatement(models.Model):
_inherit = 'account.bank.statement'
- branch_id = fields.Many2one('res.branch')
+ branch_id = fields.Many2one('res.branch', default=lambda self: self.env.user.branch_id.id)
- def _get_opening_balance(self, journal_id):
- curr_user_id = self.env['res.users'].browse(self.env.context.get('uid', False))
- last_bnk_stmt = self.search([('journal_id', '=', journal_id),('branch_id','=',curr_user_id.branch_id.id)], limit=1)
- if last_bnk_stmt:
- return last_bnk_stmt.balance_end
- return 0
+ @api.depends('create_date')
+ def _compute_balance_start(self):
+ current_user_branch_id = self.env.user.branch_id.id
+ for stmt in self.sorted(lambda x: x.first_line_index or '0'):
+ journal_id = stmt.journal_id.id or stmt.line_ids.journal_id.id
+ previous_line_with_statement = self.env['account.bank.statement.line'].search([
+ ('internal_index', '<', stmt.first_line_index),
+ ('journal_id', '=', journal_id),
+ ('state', '=', 'posted'),
+ ('statement_id', '!=', False),
+ ('branch_id', '=', current_user_branch_id),
+ ], limit=1)
+ balance_start = previous_line_with_statement.statement_id.balance_end_real
- @api.model
- def default_get(self,fields):
- res = super(AccountBankStatement, self).default_get(fields)
- branch_id = False
- if self.env.user.branch_id:
- branch_id = self.env.user.branch_id.id
- res.update({
- 'branch_id' : branch_id
- })
- return res
+ lines_in_between_domain = [
+ ('internal_index', '<', stmt.first_line_index),
+ ('journal_id', '=', journal_id),
+ ('state', '=', 'posted'),
+ ('branch_id', '=', current_user_branch_id),
+ ]
+ if previous_line_with_statement:
+ lines_in_between_domain.append(('internal_index', '>', previous_line_with_statement.internal_index))
+ # remove lines from previous statement (when multi-editing a line already in another statement)
+ previous_st_lines = previous_line_with_statement.statement_id.line_ids
+ lines_in_common = previous_st_lines.filtered(lambda l: l.id in stmt.line_ids._origin.ids)
+ balance_start -= sum(lines_in_common.mapped('amount'))
+
+ lines_in_between = self.env['account.bank.statement.line'].search(lines_in_between_domain)
+ balance_start += sum(lines_in_between.mapped('amount'))
+
+ stmt.balance_start = balance_start
- def button_confirm_bank(self):
self._balance_check()
statements = self.filtered(lambda r: r.state == 'open')
for statement in statements:
diff --git a/odex30_base/branch/models/inherited_account_bank_statement_line.py b/odex30_base/branch/models/account_bank_statement_line.py
similarity index 82%
rename from odex30_base/branch/models/inherited_account_bank_statement_line.py
rename to odex30_base/branch/models/account_bank_statement_line.py
index cdda49b..fbcca48 100644
--- a/odex30_base/branch/models/inherited_account_bank_statement_line.py
+++ b/odex30_base/branch/models/account_bank_statement_line.py
@@ -4,13 +4,12 @@
from odoo import api, fields, models, _
-class account_bank_statement_line(models.Model):
-
+class AccountBankStatementLine(models.Model):
_inherit = 'account.bank.statement.line'
@api.model
def default_get(self, default_fields):
- res = super(account_bank_statement_line, self).default_get(default_fields)
+ res = super(AccountBankStatementLine, self).default_get(default_fields)
branch_id = False
if self._context.get('branch_id'):
branch_id = self._context.get('branch_id')
diff --git a/odex30_base/branch/models/inherited_account_move.py b/odex30_base/branch/models/account_move.py
similarity index 57%
rename from odex30_base/branch/models/inherited_account_move.py
rename to odex30_base/branch/models/account_move.py
index ec6d468..0397474 100644
--- a/odex30_base/branch/models/inherited_account_move.py
+++ b/odex30_base/branch/models/account_move.py
@@ -3,6 +3,7 @@
from odoo import api, fields, models, _
from odoo.exceptions import UserError
from odoo.tools.float_utils import float_compare
+from odoo.exceptions import ValidationError
@@ -10,6 +11,8 @@ from odoo.tools.float_utils import float_compare
class AccountMove(models.Model):
_inherit = 'account.move'
+ branch_id = fields.Many2one('res.branch', string="Branch")
+
@api.model
def default_get(self, default_fields):
res = super(AccountMove, self).default_get(default_fields)
@@ -19,39 +22,24 @@ class AccountMove(models.Model):
branch_id = self._context.get('branch_id')
elif self.env.user.branch_id:
branch_id = self.env.user.branch_id.id
+
res.update({
'branch_id' : branch_id
})
return res
- branch_id = fields.Many2one('res.branch', string="Branch")
-
@api.onchange('branch_id')
def _onchange_branch_id(self):
- selected_brach = self.branch_id
- if selected_brach:
- user_id = self.env.user
- user_branch = user_id.sudo().branch_id
- if user_branch and user_branch.id != selected_brach.id:
+ selected_branch = self.branch_id
+ if selected_branch:
+ user_branch = self.env.user.branch_id
+ if user_branch and user_branch.id != selected_branch.id:
raise UserError("Please select active branch only. Other may create the Multi branch issue. \n\ne.g: If you wish to add other branch then Switch branch from the header and set that.")
class AccountMoveLine(models.Model):
_inherit = 'account.move.line'
- @api.model
- def default_get(self, default_fields):
- res = super(AccountMoveLine, self).default_get(default_fields)
- branch_id = False
+ branch_id = fields.Many2one('res.branch', string="Branch", related="move_id.branch_id", store=True)
+
- if self._context.get('branch_id'):
- branch_id = self._context.get('branch_id')
- elif self.env.user.branch_id:
- branch_id = self.env.user.branch_id.id
-
- if self.move_id.branch_id :
- branch_id = self.move_id.branch_id.id
- res.update({'branch_id' : branch_id})
- return res
-
- branch_id = fields.Many2one('res.branch', string="Branch",related="move_id.branch_id",store=True)
diff --git a/odex30_base/branch/models/inherited_stock_warehouse.py b/odex30_base/branch/models/account_payment.py
similarity index 51%
rename from odex30_base/branch/models/inherited_stock_warehouse.py
rename to odex30_base/branch/models/account_payment.py
index 6c736de..7c57910 100644
--- a/odex30_base/branch/models/inherited_stock_warehouse.py
+++ b/odex30_base/branch/models/account_payment.py
@@ -3,23 +3,14 @@
from odoo import api, fields, models, _
from odoo.exceptions import UserError
-class StockWarehouse(models.Model):
- _inherit = 'stock.warehouse'
+class AccountPayment(models.Model):
+ _inherit = 'account.payment'
branch_id = fields.Many2one('res.branch')
@api.onchange('branch_id')
def _onchange_branch_id(self):
- selected_brach = self.branch_id
- if selected_brach:
- user_id = self.env.user
- user_branch = user_id.sudo().branch_id
- if user_branch and user_branch.id != selected_brach.id:
+ if self.branch_id:
+ user_branch = self.env.user.branch_id
+ if user_branch and user_branch.id != self.branch_id.id:
raise UserError("Please select active branch only. Other may create the Multi branch issue. \n\ne.g: If you wish to add other branch then Switch branch from the header and set that.")
-
-
-
-class StockPickingTypeIn(models.Model):
- _inherit = 'stock.picking.type'
-
- branch_id = fields.Many2one('res.branch',related='warehouse_id.branch_id', store=True,)
diff --git a/odex30_base/branch/models/inherited_account_payment.py b/odex30_base/branch/models/inherited_account_payment.py
deleted file mode 100644
index ae8da45..0000000
--- a/odex30_base/branch/models/inherited_account_payment.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# Part of BrowseInfo. See LICENSE file for full copyright and licensing details.
-
-from odoo import api, fields, models, _
-from odoo.exceptions import UserError
-
-MAP_INVOICE_TYPE_PARTNER_TYPE = {
- 'out_invoice': 'customer',
- 'out_refund': 'customer',
- 'in_invoice': 'supplier',
- 'in_refund': 'supplier',
-}
-
-class AccountPayment(models.Model):
- _inherit = 'account.payment'
-
- @api.model
- def default_get(self, fields):
- rec = super(AccountPayment, self).default_get(fields)
- invoice_defaults = self.reconciled_invoice_ids
- if invoice_defaults and len(invoice_defaults) == 1:
- invoice = invoice_defaults[0]
- rec['branch_id'] = invoice.branch_id.id
- return rec
-
- branch_id = fields.Many2one('res.branch')
-
- @api.onchange('branch_id')
- def _onchange_branch_id(self):
- selected_brach = self.branch_id
- if selected_brach:
- user_id = self.env.user
- user_branch = user_id.sudo().branch_id
- if user_branch and user_branch.id != selected_brach.id:
- raise UserError("Please select active branch only. Other may create the Multi branch issue. \n\ne.g: If you wish to add other branch then Switch branch from the header and set that.")
diff --git a/odex30_base/branch/models/inherited_customer.py b/odex30_base/branch/models/inherited_customer.py
deleted file mode 100644
index 6c5ac64..0000000
--- a/odex30_base/branch/models/inherited_customer.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# Part of BrowseInfo. See LICENSE file for full copyright and licensing details.
-
-from odoo import api, fields, models, _
-
-
-class ResPartnerIn(models.Model):
- _inherit = 'res.partner'
-
-
- @api.model
- def default_get(self, default_fields):
- res = super(ResPartnerIn, self).default_get(default_fields)
- if self.env.user.branch_id:
- res.update({
- 'branch_id' : self.env.user.branch_id.id or False
- })
- return res
-
- branch_id = fields.Many2one('res.branch', string="Branch")
\ No newline at end of file
diff --git a/odex30_base/branch/models/inherited_product.py b/odex30_base/branch/models/inherited_product.py
deleted file mode 100644
index b1ffccd..0000000
--- a/odex30_base/branch/models/inherited_product.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# Part of BrowseInfo. See LICENSE file for full copyright and licensing details.
-
-from odoo import api, fields, models, _
-
-
-class ProductTemplateIn(models.Model):
- _inherit = 'product.template'
-
-
- @api.model
- def default_get(self, default_fields):
- res = super(ProductTemplateIn, self).default_get(default_fields)
- if self.env.user.branch_id:
- res.update({
- 'branch_id' : self.env.user.branch_id.id or False
- })
- return res
-
- branch_id = fields.Many2one('res.branch', string="Branch")
\ No newline at end of file
diff --git a/odex30_base/branch/models/inherited_stock_inventory.py b/odex30_base/branch/models/inherited_stock_inventory.py
deleted file mode 100644
index 4576f53..0000000
--- a/odex30_base/branch/models/inherited_stock_inventory.py
+++ /dev/null
@@ -1,46 +0,0 @@
-# Part of BrowseInfo. See LICENSE file for full copyright and licensing details.
-
-from odoo import api, fields, models, _
-from odoo.exceptions import UserError
-
-
-class stock_inventory(models.Model):
- _inherit = 'stock.inventory'
-
-
- @api.model
- def default_get(self,fields):
- res = super(stock_inventory, self).default_get(fields)
- if res.get('location_id'):
- location_branch = self.env['stock.location'].browse(res.get('location_id')).branch_id.id
- if location_branch:
- res['branch_id'] = location_branch
- else:
- user_branch = self.env.user.branch_id
- if user_branch:
- res['branch_id'] = user_branch.id
- return res
-
- branch_id = fields.Many2one('res.branch')
-
-
- def post_inventory(self):
- # The inventory is posted as a single step which means quants cannot be moved from an internal location to another using an inventory
- # as they will be moved to inventory loss, and other quants will be created to the encoded quant location. This is a normal behavior
- # as quants cannot be reuse from inventory location (users can still manually move the products before/after the inventory if they want).
- self.mapped('move_ids').filtered(lambda move: move.state != 'done')._action_done()
- for move_id in self.move_ids:
- account_move =self.env['account.move'].search([('stock_move_id','=',move_id.id)])
- account_move.write({'branch_id':self.branch_id.id})
- for line in account_move.line_ids:
- line.write({'branch_id':self.branch_id.id})
-
-
- @api.onchange('branch_id')
- def _onchange_branch_id(self):
- selected_brach = self.branch_id
- if selected_brach:
- user_id = self.env.user
- user_branch = user_id.sudo().branch_id
- if user_branch and user_branch.id != selected_brach.id:
- raise UserError("Please select active branch only. Other may create the Multi branch issue. \n\ne.g: If you wish to add other branch then Switch branch from the header and set that.")
\ No newline at end of file
diff --git a/odex30_base/branch/models/inherited_stock_move.py b/odex30_base/branch/models/inherited_stock_move.py
deleted file mode 100644
index 606408b..0000000
--- a/odex30_base/branch/models/inherited_stock_move.py
+++ /dev/null
@@ -1,82 +0,0 @@
-# Part of BrowseInfo. See LICENSE file for full copyright and licensing details.
-
-from odoo import api, fields, models, _
-from odoo.exceptions import UserError
-from itertools import groupby
-
-class StockMove(models.Model):
- _inherit = 'stock.move'
-
- branch_id = fields.Many2one('res.branch')
-
- def _assign_picking(self):
- """ Try to assign the moves to an existing picking that has not been
- reserved yet and has the same procurement group, locations and picking
- type (moves should already have them identical). Otherwise, create a new
- picking to assign them to. """
- Picking = self.env['stock.picking']
- grouped_moves = groupby(sorted(self, key=lambda m: [f.id for f in m._key_assign_picking()]), key=lambda m: [m._key_assign_picking()])
- for group, moves in grouped_moves:
- moves = self.env['stock.move'].concat(*list(moves))
- branch_id = self.group_id.sale_id.branch_id.id if self.group_id.sale_id and self.group_id.sale_id.branch_id else False
- moves.write({'branch_id': branch_id})
- new_picking = False
- # Could pass the arguments contained in group but they are the same
- # for each move that why moves[0] is acceptable
- picking = moves[0]._search_picking_for_assignation()
- if picking:
- if any(picking.partner_id.id != m.partner_id.id or
- picking.origin != m.origin for m in moves):
- # If a picking is found, we'll append `move` to its move list and thus its
- # `partner_id` and `ref` field will refer to multiple records. In this
- # case, we chose to wipe them.
- picking.write({
- 'partner_id': False,
- 'origin': False,
- })
- else:
- new_picking = True
- picking = Picking.create(moves._get_new_picking_values())
-
- moves.write({'picking_id': picking.id})
- moves._assign_picking_post_process(new=new_picking)
- return True
-
- def _get_new_picking_values(self):
- vals = super(StockMove, self)._get_new_picking_values()
- vals['branch_id'] = self.group_id.sale_id.branch_id.id
- return vals
-
- def _create_account_move_line(self, credit_account_id, debit_account_id, journal_id, qty, description, svl_id, cost):
- self.ensure_one()
- AccountMove = self.env['account.move'].with_context(default_journal_id=journal_id)
-
- move_lines = self._prepare_account_move_line(qty, cost, credit_account_id, debit_account_id, description)
- if move_lines:
- date = self._context.get('force_period_date', fields.Date.context_today(self))
- new_account_move = AccountMove.sudo().create({
- 'journal_id': journal_id,
- 'line_ids': move_lines,
- 'date': date,
- 'ref': description,
- 'stock_move_id': self.id,
- 'stock_valuation_layer_ids': [(6, None, [svl_id])],
- 'move_type': 'entry',
- 'branch_id': self.picking_id.branch_id.id or self.branch_id.id or False,
- })
- new_account_move._post()
-
- def _generate_valuation_lines_data(self, partner_id, qty, debit_value, credit_value, debit_account_id, credit_account_id, description):
- # This method returns a dictionary to provide an easy extension hook to modify the valuation lines (see purchase for an example)
- result = super(StockMove, self)._generate_valuation_lines_data(partner_id, qty, debit_value, credit_value, debit_account_id, credit_account_id, description)
-
- branch_id = False
- if self.branch_id:
- branch_id = self.branch_id.id
- elif self.env.user.branch_id:
- branch_id = self.env.user.branch_id.id
-
- for res in result:
- result[res].update({'branch_id' : branch_id})
-
- return result
\ No newline at end of file
diff --git a/odex30_base/branch/models/ir_http.py b/odex30_base/branch/models/ir_http.py
index b4116a7..39ec892 100644
--- a/odex30_base/branch/models/ir_http.py
+++ b/odex30_base/branch/models/ir_http.py
@@ -1,65 +1,21 @@
# -*- coding: utf-8 -*-
# Part of BrowseInfo. See LICENSE file for full copyright and licensing details.
-import hashlib
-import json
-from odoo import api, models
+from odoo import models
from odoo.http import request
-from odoo.tools import ustr
-from odoo.addons.web.controllers.main import module_boot, HomeStaticTemplateHelpers
-import odoo
class Http(models.AbstractModel):
_inherit = 'ir.http'
def session_info(self):
+ res = super(Http, self).session_info()
user = request.env.user
- version_info = odoo.service.common.exp_version()
-
- user_context = request.session.get_context() if request.session.uid else {}
-
- session_info = {
- "uid": request.session.uid,
- "is_system": user._is_system() if request.session.uid else False,
- "is_admin": user._is_admin() if request.session.uid else False,
- "user_context": request.session.get_context() if request.session.uid else {},
- "db": request.session.db,
- "server_version": version_info.get('server_version'),
- "server_version_info": version_info.get('server_version_info'),
- "name": user.name,
- "username": user.login,
- "partner_display_name": user.partner_id.display_name,
- "company_id": user.company_id.id if request.session.uid else None, # YTI TODO: Remove this from the user context
+ res.update({
"branch_id": user.branch_id.id if request.session.uid else None,
- "partner_id": user.partner_id.id if request.session.uid and user.partner_id else None,
- "web.base.url": self.env['ir.config_parameter'].sudo().get_param('web.base.url', default=''),
- }
- if self.env.user.has_group('base.group_user'):
- # the following is only useful in the context of a webclient bootstrapping
- # but is still included in some other calls (e.g. '/web/session/authenticate')
- # to avoid access errors and unnecessary information, it is only included for users
- # with access to the backend ('internal'-type users)
- mods = module_boot()
- qweb_checksum = HomeStaticTemplateHelpers.get_qweb_templates_checksum(addons=mods, debug=request.session.debug)
- lang = user_context.get("lang")
- translation_hash = request.env['ir.translation'].get_web_translations_hash(mods, lang)
- menu_json_utf8 = json.dumps(request.env['ir.ui.menu'].load_menus(request.session.debug), default=ustr, sort_keys=True).encode()
- cache_hashes = {
- "load_menus": hashlib.sha1(menu_json_utf8).hexdigest(),
- "qweb": qweb_checksum,
- "translations": translation_hash,
- }
- session_info.update({
- # current_company should be default_company
- "user_companies": {'current_company': (user.company_id.id, user.company_id.name), 'allowed_companies': [(comp.id, comp.name) for comp in user.company_ids]},
- "user_branches": {'current_branch': (user.branch_id.id, user.branch_id.name), 'allowed_branch': [(comp.id, comp.name) for comp in user.branch_ids]},
- "currencies": self.get_currencies(),
- "show_effect": True,
- "display_switch_company_menu": user.has_group('base.group_multi_company') and len(user.company_ids) > 1,
- "display_switch_branch_menu": user.has_group('branch.group_multi_branch') and len(user.branch_ids) > 1,
- "cache_hashes": cache_hashes,
- "allowed_branch_ids" : user.branch_id.ids
- })
- return session_info
+ "user_branches": {'current_branch': (user.branch_id.id, user.branch_id.name),
+ "allowed_branch": [(comp.id, comp.name) for comp in user.branch_ids]},
+ "allowed_branch_ids" : user.branch_id.ids,
+ "display_switch_branch_menu": user.has_group('branch.group_multi_branch') and len(user.branch_ids) > 1,
+ })
+ return res
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
diff --git a/odex30_base/branch/models/product.py b/odex30_base/branch/models/product.py
new file mode 100644
index 0000000..81d4813
--- /dev/null
+++ b/odex30_base/branch/models/product.py
@@ -0,0 +1,9 @@
+# Part of BrowseInfo. See LICENSE file for full copyright and licensing details.
+
+from odoo import api, fields, models, _
+
+
+class ProductTemplateIn(models.Model):
+ _inherit = 'product.template'
+
+ branch_id = fields.Many2one('res.branch', string="Branch", default=lambda self: self.env.user.branch_id.id)
\ No newline at end of file
diff --git a/odex30_base/branch/models/inherited_purchase_order.py b/odex30_base/branch/models/purchase_order.py
similarity index 67%
rename from odex30_base/branch/models/inherited_purchase_order.py
rename to odex30_base/branch/models/purchase_order.py
index f064b77..0d0f6c1 100644
--- a/odex30_base/branch/models/inherited_purchase_order.py
+++ b/odex30_base/branch/models/purchase_order.py
@@ -1,23 +1,85 @@
# Part of BrowseInfo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models, _
-from odoo.exceptions import UserError
+from odoo.exceptions import ValidationError
+
+
+class PurchaseOrder(models.Model):
+ _inherit = 'purchase.order'
+
+ branch_id = fields.Many2one('res.branch', string='Branch')
+
+ @api.model
+ def default_get(self,fields):
+ res = super(PurchaseOrder, self).default_get(fields)
+ branch_id = picking_type_id = False
+
+ if self.env.user.branch_id:
+ branch_id = self.env.user.branch_id.id
+
+ if branch_id:
+ branched_warehouse = self.env['stock.warehouse'].search([('branch_id','=',branch_id)])
+ if branched_warehouse:
+ picking_type_id = branched_warehouse[0].in_type_id.id
+ else:
+ picking_type_id = self._default_picking_type().id
+
+ res.update({
+ 'branch_id' : branch_id,
+ 'picking_type_id' : picking_type_id
+ })
+
+ return res
+
+ def _prepare_picking(self):
+ res = super(PurchaseOrder, self)._prepare_picking()
+
+ branch_id = False
+ if self.branch_id:
+ branch_id = self.branch_id.id
+ elif self.env.user.branch_id:
+ branch_id = self.env.user.branch_id.id
+
+ res.update({
+ 'branch_id' : branch_id
+ })
+ return res
+
+ def _prepare_invoice(self):
+ result = super(PurchaseOrder, self)._prepare_invoice()
+
+ branch_id = False
+ if self.branch_id:
+ branch_id = self.branch_id.id
+ elif self.env.user.branch_id:
+ branch_id = self.env.user.branch_id.id
+
+ result.update({
+ 'branch_id' : branch_id
+ })
+
+ return result
+
+ @api.onchange('branch_id')
+ def _onchange_branch_id(self):
+ if self.branch_id:
+ user_branch = self.env.user.sudo().branch_id
+ if user_branch and user_branch.id != self.branch_id.id:
+ raise ValidationError("Please select active branch only. Other may create the Multi branch issue. \n\ne.g: If you wish to add other branch then Switch branch from the header and set that.")
class purchase_order(models.Model):
-
_inherit = 'purchase.order.line'
+ branch_id = fields.Many2one('res.branch', string="Branch", related="order_id.branch_id", store=True)
def _prepare_account_move_line(self, move=False):
result = super(purchase_order, self)._prepare_account_move_line(move)
result.update({
- 'branch_id' : self.order_id.branch_id.id or False,
-
+ 'branch_id' : self.order_id.branch_id.id,
})
return result
-
@api.model
def default_get(self, default_fields):
res = super(purchase_order, self).default_get(default_fields)
@@ -29,9 +91,6 @@ class purchase_order(models.Model):
res.update({'branch_id' : branch_id})
return res
- branch_id = fields.Many2one('res.branch', string="Branch")
-
-
def _prepare_stock_moves(self, picking):
result = super(purchase_order, self)._prepare_stock_moves(picking)
@@ -46,92 +105,3 @@ class purchase_order(models.Model):
return result
-
-class PurchaseOrder(models.Model):
- _inherit = 'purchase.order'
-
-
- @api.model
- def default_get(self,fields):
- res = super(PurchaseOrder, self).default_get(fields)
- branch_id = picking_type_id = False
-
- if self.env.user.branch_id:
- branch_id = self.env.user.branch_id.id
-
- if branch_id:
- branched_warehouse = self.env['stock.warehouse'].search([('branch_id','=',branch_id)])
- if branched_warehouse:
- picking_type_id = branched_warehouse[0].in_type_id.id
- else:
- picking = self._default_picking_type()
- picking_type_id = picking.id
-
- res.update({
- 'branch_id' : branch_id,
- 'picking_type_id' : picking_type_id
- })
-
- return res
-
- branch_id = fields.Many2one('res.branch', string='Branch')
-
- @api.model
- def _prepare_picking(self):
- res = super(PurchaseOrder, self)._prepare_picking()
- branch_id = False
- if self.branch_id:
- branch_id = self.branch_id.id
- elif self.env.user.branch_id:
- branch_id = self.env.user.branch_id.id
- res.update({
- 'branch_id' : branch_id
- })
- return res
-
-
- def _prepare_invoice(self):
- result = super(PurchaseOrder, self)._prepare_invoice()
- branch_id = False
- if self.branch_id:
- branch_id = self.branch_id.id
- elif self.env.user.branch_id:
- branch_id = self.env.user.branch_id.id
-
- result.update({
-
- 'branch_id' : branch_id
- })
-
- return result
- def action_view_invoice(self, invoices=False):
- '''
- This function returns an action that display existing vendor bills of given purchase order ids.
- When only one found, show the vendor bill immediately.
- '''
-
- result = super(PurchaseOrder, self).action_view_invoice(invoices)
-
- branch_id = False
- if self.branch_id:
- branch_id = self.branch_id.id
- elif self.env.user.branch_id:
- branch_id = self.env.user.branch_id.id
-
-
- result.update({
-
- 'branch_id' : branch_id
- })
-
-
- return result
-
- @api.onchange('branch_id')
- def _onchange_branch_id(self):
- selected_brach = self.branch_id
- if selected_brach:
- user_id = self.env.user
- user_branch = user_id.sudo().branch_id
- if user_branch and user_branch.id != selected_brach.id:
- raise UserError("Please select active branch only. Other may create the Multi branch issue. \n\ne.g: If you wish to add other branch then Switch branch from the header and set that.")
\ No newline at end of file
diff --git a/odex30_base/branch/models/res_partner.py b/odex30_base/branch/models/res_partner.py
new file mode 100644
index 0000000..7aa49a2
--- /dev/null
+++ b/odex30_base/branch/models/res_partner.py
@@ -0,0 +1,9 @@
+# Part of BrowseInfo. See LICENSE file for full copyright and licensing details.
+
+from odoo import api, fields, models, _
+
+
+class ResPartnerIn(models.Model):
+ _inherit = 'res.partner'
+
+ branch_id = fields.Many2one('res.branch', string="Branch", default=lambda self: self.env.user.branch_id.id)
\ No newline at end of file
diff --git a/odex30_base/branch/models/inherited_res_users.py b/odex30_base/branch/models/res_users.py
similarity index 85%
rename from odex30_base/branch/models/inherited_res_users.py
rename to odex30_base/branch/models/res_users.py
index d278b0d..a246e59 100644
--- a/odex30_base/branch/models/inherited_res_users.py
+++ b/odex30_base/branch/models/res_users.py
@@ -12,7 +12,6 @@ class ResUsers(models.Model):
def write(self, values):
if 'branch_id' in values or 'branch_ids' in values:
self.env['ir.model.access'].call_cache_clearing_methods()
- self.env['ir.rule'].clear_caches()
- # self.has_group.clear_cache(self)
+
user = super(ResUsers, self).write(values)
return user
diff --git a/odex30_base/branch/models/inherited_sale_order.py b/odex30_base/branch/models/sale_order.py
similarity index 76%
rename from odex30_base/branch/models/inherited_sale_order.py
rename to odex30_base/branch/models/sale_order.py
index 93ddbc0..5539210 100644
--- a/odex30_base/branch/models/inherited_sale_order.py
+++ b/odex30_base/branch/models/sale_order.py
@@ -7,6 +7,7 @@ from odoo.exceptions import UserError
class SaleOrder(models.Model):
_inherit = 'sale.order'
+ branch_id = fields.Many2one('res.branch', string="Branch")
@api.model
def default_get(self,fields):
@@ -18,31 +19,26 @@ class SaleOrder(models.Model):
branched_warehouse = self.env['stock.warehouse'].search([('branch_id','=',branch_id)])
if branched_warehouse:
warehouse_id = branched_warehouse.ids[0]
- else:
- warehouse_id = self._default_warehouse_id()
- warehouse_id = warehouse_id.id
res.update({
'branch_id' : branch_id,
- 'warehouse_id' : warehouse_id
+ })
+
+ if warehouse_id:
+ res.update({
+ 'warehouse_id' : warehouse_id
})
return res
- branch_id = fields.Many2one('res.branch', string="Branch")
-
-
def _prepare_invoice(self):
res = super(SaleOrder, self)._prepare_invoice()
res['branch_id'] = self.branch_id.id
return res
-
@api.onchange('branch_id')
def _onchange_branch_id(self):
- selected_brach = self.branch_id
- if selected_brach:
- user_id = self.env.user
- user_branch = user_id.sudo().branch_id
- if user_branch and user_branch.id != selected_brach.id:
+ if self.branch_id:
+ user_branch = self.env.user.sudo().branch_id
+ if user_branch and user_branch.id != self.branch_id.id:
raise UserError("Please select active branch only. Other may create the Multi branch issue. \n\ne.g: If you wish to add other branch then Switch branch from the header and set that.")
\ No newline at end of file
diff --git a/odex30_base/branch/models/inherited_stock_location.py b/odex30_base/branch/models/stock_location.py
similarity index 64%
rename from odex30_base/branch/models/inherited_stock_location.py
rename to odex30_base/branch/models/stock_location.py
index 5da195f..d2eed85 100644
--- a/odex30_base/branch/models/inherited_stock_location.py
+++ b/odex30_base/branch/models/stock_location.py
@@ -3,6 +3,20 @@
from odoo import api, fields, models, _
from odoo.exceptions import UserError
+class StockWarehouse(models.Model):
+ _inherit = 'stock.warehouse'
+
+ branch_id = fields.Many2one('res.branch')
+
+ @api.onchange('branch_id')
+ def _onchange_branch_id(self):
+ selected_brach = self.branch_id
+ if selected_brach:
+ user_id = self.env['res.users'].browse(self.env.uid)
+ user_branch = user_id.sudo().branch_id
+ if user_branch and user_branch.id != selected_brach.id:
+ raise Warning("Please select active branch only. Other may create the Multi branch issue. \n\ne.g: If you wish to add other branch then Switch branch from the header and set that.")
+
class StockLocation(models.Model):
_inherit = 'stock.location'
@@ -24,7 +38,7 @@ class StockLocation(models.Model):
def _onchange_branch_id(self):
selected_brach = self.branch_id
if selected_brach:
- user_id = self.env.user
+ user_id = self.env['res.users'].browse(self.env.uid)
user_branch = user_id.sudo().branch_id
if user_branch and user_branch.id != selected_brach.id:
raise UserError("Please select active branch only. Other may create the Multi branch issue. \n\ne.g: If you wish to add other branch then Switch branch from the header and set that.")
\ No newline at end of file
diff --git a/odex30_base/branch/models/stock_move.py b/odex30_base/branch/models/stock_move.py
new file mode 100644
index 0000000..ce82393
--- /dev/null
+++ b/odex30_base/branch/models/stock_move.py
@@ -0,0 +1,38 @@
+# Part of BrowseInfo. See LICENSE file for full copyright and licensing details.
+
+from odoo import fields, models
+
+class StockMove(models.Model):
+ _inherit = 'stock.move'
+
+ branch_id = fields.Many2one('res.branch')
+
+ def _assign_picking(self):
+ branch_id = self.group_id.sale_id.branch_id.id if self.group_id.sale_id and self.group_id.sale_id.branch_id else False
+ self.write({'branch_id': branch_id})
+ return super(StockMove, self)._assign_picking()
+
+ def _get_new_picking_values(self):
+ vals = super(StockMove, self)._get_new_picking_values()
+ vals['branch_id'] = self.group_id.sale_id.branch_id.id
+ return vals
+
+ def _prepare_account_move_vals(self, credit_account_id, debit_account_id, journal_id, qty, description, svl_id, cost):
+ res = super(StockMove, self)._prepare_account_move_vals(credit_account_id, debit_account_id, journal_id, qty, description, svl_id, cost)
+ res['branch_id'] = self.picking_id.branch_id.id or self.branch_id.id or False
+ return res
+
+ def _generate_valuation_lines_data(self, partner_id, qty, debit_value, credit_value, debit_account_id, credit_account_id, description):
+ # This method returns a dictionary to provide an easy extension hook to modify the valuation lines (see purchase for an example)
+ result = super(StockMove, self)._generate_valuation_lines_data(partner_id, qty, debit_value, credit_value, debit_account_id, credit_account_id, description)
+
+ branch_id = False
+ if self.branch_id:
+ branch_id = self.branch_id.id
+ elif self.env.user.branch_id:
+ branch_id = self.env.user.branch_id.id
+
+ for res in result.keys():
+ result[res].update({'branch_id' : branch_id})
+
+ return result
\ No newline at end of file
diff --git a/odex30_base/branch/models/inherited_stock_picking.py b/odex30_base/branch/models/stock_picking.py
similarity index 71%
rename from odex30_base/branch/models/inherited_stock_picking.py
rename to odex30_base/branch/models/stock_picking.py
index 63dedaf..8fefe1a 100644
--- a/odex30_base/branch/models/inherited_stock_picking.py
+++ b/odex30_base/branch/models/stock_picking.py
@@ -1,12 +1,14 @@
# Part of BrowseInfo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models, _
-from odoo.exceptions import UserError
+from odoo.exceptions import ValidationError
class StockPicking(models.Model):
_inherit = 'stock.picking'
+ branch_id = fields.Many2one('res.branch', string="Branch")
+
@api.model
def default_get(self, default_fields):
res = super(StockPicking, self).default_get(default_fields)
@@ -16,13 +18,11 @@ class StockPicking(models.Model):
})
return res
- branch_id = fields.Many2one('res.branch', string="Branch")
-
@api.onchange('branch_id')
def _onchange_branch_id(self):
selected_brach = self.branch_id
if selected_brach:
- user_id = self.env.user
+ user_id = self.env['res.users'].browse(self.env.uid)
user_branch = user_id.sudo().branch_id
if user_branch and user_branch.id != selected_brach.id:
- raise UserError("Please select active branch only. Other may create the Multi branch issue. \n\ne.g: If you wish to add other branch then Switch branch from the header and set that.")
\ No newline at end of file
+ raise ValidationError("Please select active branch only. Other may create the Multi branch issue. \n\ne.g: If you wish to add other branch then Switch branch from the header and set that.")
\ No newline at end of file
diff --git a/odex30_base/branch/models/stock_picking_type.py b/odex30_base/branch/models/stock_picking_type.py
new file mode 100644
index 0000000..da4f779
--- /dev/null
+++ b/odex30_base/branch/models/stock_picking_type.py
@@ -0,0 +1,9 @@
+# Part of BrowseInfo. See LICENSE file for full copyright and licensing details.
+
+from odoo import fields, models
+
+
+class StockPickingTypeIn(models.Model):
+ _inherit = 'stock.picking.type'
+
+ branch_id = fields.Many2one('res.branch',related='warehouse_id.branch_id', store=True,)
diff --git a/odex30_base/branch/reports/__init__.py b/odex30_base/branch/reports/__init__.py
deleted file mode 100644
index 798a488..0000000
--- a/odex30_base/branch/reports/__init__.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# Part of BrowseInfo. See LICENSE file for full copyright and licensing details.
-
-from . import inherited_sale_report
-from . import inherited_account_invoice_report
-from . import inherited_purchase_report
-
-
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/odex30_base/branch/reports/inherited_account_invoice_report.py b/odex30_base/branch/reports/account_invoice_report.py
similarity index 61%
rename from odex30_base/branch/reports/inherited_account_invoice_report.py
rename to odex30_base/branch/reports/account_invoice_report.py
index 63f29cf..73a56ff 100644
--- a/odex30_base/branch/reports/inherited_account_invoice_report.py
+++ b/odex30_base/branch/reports/account_invoice_report.py
@@ -1,6 +1,8 @@
# Part of BrowseInfo. See LICENSE file for full copyright and licensing details.
from odoo import fields, models
+from odoo.tools import SQL
+
class AccountInvoiceReport(models.Model):
@@ -8,5 +10,6 @@ class AccountInvoiceReport(models.Model):
branch_id = fields.Many2one('res.branch')
- def _select(self):
- return super(AccountInvoiceReport, self)._select() + ", move.branch_id"
\ No newline at end of file
+ def _select(self) -> SQL:
+ return SQL("%s, , move.branch_id AS branch_id",
+ super()._select())
diff --git a/odex30_base/branch/reports/inherited_sale_report.py b/odex30_base/branch/reports/inherited_sale_report.py
deleted file mode 100644
index 2ec518c..0000000
--- a/odex30_base/branch/reports/inherited_sale_report.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Part of BrowseInfo. See LICENSE file for full copyright and licensing details.
-
-from odoo import fields, models
-
-
-class SaleReport(models.Model):
- _inherit = "sale.report"
-
- branch_id = fields.Many2one('res.branch')
-
- def _query(self, with_clause='', fields={}, groupby='', from_clause=''):
- fields['branch_id'] = ", s.branch_id as branch_id"
- return super(SaleReport, self)._query(with_clause, fields, groupby, from_clause)
-
diff --git a/odex30_base/branch/reports/inherited_purchase_report.py b/odex30_base/branch/reports/purchase_report.py
similarity index 50%
rename from odex30_base/branch/reports/inherited_purchase_report.py
rename to odex30_base/branch/reports/purchase_report.py
index 32fde6b..7437270 100644
--- a/odex30_base/branch/reports/inherited_purchase_report.py
+++ b/odex30_base/branch/reports/purchase_report.py
@@ -1,15 +1,16 @@
# Part of BrowseInfo. See LICENSE file for full copyright and licensing details.
from odoo import fields, models
+from odoo.tools import SQL
class PurchaseReport(models.Model):
_inherit = "purchase.report"
branch_id = fields.Many2one('res.branch')
+
+ def _select(self) -> SQL:
+ return SQL("%s, po.branch_id AS branch_id", super()._select())
- def _select(self):
- return super(PurchaseReport, self)._select() + ", po.branch_id as branch_id"
-
- def _group_by(self):
- return super(PurchaseReport, self)._group_by() + ", po.branch_id"
\ No newline at end of file
+ def _group_by(self) -> SQL:
+ return SQL("%s, po.branch_id", super()._group_by())
\ No newline at end of file
diff --git a/odex30_base/branch/reports/sale_report.py b/odex30_base/branch/reports/sale_report.py
new file mode 100644
index 0000000..9bab6b3
--- /dev/null
+++ b/odex30_base/branch/reports/sale_report.py
@@ -0,0 +1,15 @@
+# Part of BrowseInfo. See LICENSE file for full copyright and licensing details.
+
+from odoo import fields, models
+from odoo.tools import SQL
+
+
+class SaleReport(models.Model):
+ _inherit = "sale.report"
+
+ branch_id = fields.Many2one('res.branch')
+
+ def _select_additional_fields(self):
+ res = super()._select_additional_fields()
+ res['branch_id'] = 's.branch_id'
+ return res
\ No newline at end of file
diff --git a/odex30_base/branch/security/branch_security.xml b/odex30_base/branch/security/branch_security.xml
index c63bb1b..449f75b 100644
--- a/odex30_base/branch/security/branch_security.xml
+++ b/odex30_base/branch/security/branch_security.xml
@@ -1,6 +1,11 @@
-
+
+
+
+ Multi Branches
+
+
Branch
@@ -9,255 +14,213 @@
User
-
-
+
+
Manager
-
-
-
+
+
+
-
+
Res Branch Manager
-
-
+
+
[(1,'=',1)]
-
+
Res Branch User
-
-
+
+
[('id','=',user.branch_id.id)]
-
+
-
-
- Personal Orders
-
- ['|',('branch_id','=',user.branch_id.id),('branch_id','=',False),('user_id','=',user.id)]
-
-
-
-
- All Branch Orders
-
- ['|',('branch_id','=',False),('branch_id','=',user.branch_id.id)]
-
+
+ Own Branch Orders
+
+ ['|',('branch_id','=',user.branch_id.id),('branch_id','=',False)]
+
All Orders
-
+
[(1,'=',1)]
-
+
-
Purchase Branch Manager
-
-
+
+
[(1,'=',1)]
-
+
-
-
-
Purchase Branch
-
-
+
+
['|',('branch_id','=',False),('branch_id','=',user.branch_id.id)]
-
+
-
+
Picking Branch Manager
-
-
+
+
[(1,'=',1)]
-
+
-
+
Picking Branch
-
-
+
+
['|',('branch_id','=',False),('branch_id','=',user.branch_id.id)]
-
+
-
+
Warehouse Branch Manager
-
-
+
+
[(1,'=',1)]
-
+
-
+
Warehouse Branch
-
-
+
+
['|',('branch_id','=',False),('branch_id','=',user.branch_id.id)]
-
+
-
+
Location Branch Manager
-
-
+
+
[(1,'=',1)]
-
+
-
+
Location Branch
-
-
+
+
['|',('branch_id','=',False),('branch_id','=',user.branch_id.id)]
-
+
Picking Type Branch Manager
-
-
+
+
[(1,'=',1)]
-
+
-
+
Picking Type Branch
-
-
+
+
['|',('branch_id','=',False),('branch_id','=',user.branch_id.id)]
-
+
Stock Quant Branch Manager
-
-
+
+
[(1,'=',1)]
-
+
-
+
Stock Quant Branch
-
-
- ['|',('location_id.branch_id','=',False),('location_id.branch_id','=',user.branch_id.id)]
-
+
+
+
+ ['|',('location_id.branch_id','=',False),('location_id.branch_id','=',user.branch_id.id)]
+
Stock Move Line Branch Manager
-
-
+
+
[(1,'=',1)]
-
+
-
+
Stock Move Line Branch
-
-
- ['|',('location_dest_id.branch_id','=',False),('location_dest_id.branch_id','=',user.branch_id.id)]
-
+
+
+
+ ['|',('location_dest_id.branch_id','=',False),('location_dest_id.branch_id','=',user.branch_id.id)]
+
Warehouse Branch Manager
-
-
+
+
[(1,'=',1)]
-
+
-
+
Warehouse Branch
-
-
+
+
['|',('branch_id','=',False),('branch_id','=',user.branch_id.id)]
-
+
Product Template Branch Manager
-
-
+
+
[(1,'=',1)]
-
+
Product Template Branch
-
-
+
+
['|',('branch_id','=',False),('branch_id','=',user.branch_id.id)]
-
+
Product Product Branch Manager
-
-
+
+
[(1,'=',1)]
-
+
-
+
Product Product Branch
-
-
- ['|',('product_tmpl_id.branch_id','=',False),('product_tmpl_id.branch_id','=',user.branch_id.id)]
-
+
+
+
+ ['|',('product_tmpl_id.branch_id','=',False),('product_tmpl_id.branch_id','=',user.branch_id.id)]
+
-
-
-
-
-
-
diff --git a/odex30_base/branch/security/multi_branch.xml b/odex30_base/branch/security/multi_branch.xml
deleted file mode 100644
index 0041133..0000000
--- a/odex30_base/branch/security/multi_branch.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
- Multi Branches
-
-
-
\ No newline at end of file
diff --git a/odex30_base/branch/static/description/Banner.gif b/odex30_base/branch/static/description/Banner.gif
new file mode 100755
index 0000000..dd8718a
Binary files /dev/null and b/odex30_base/branch/static/description/Banner.gif differ
diff --git a/odex30_base/branch/static/description/branch1.png b/odex30_base/branch/static/description/branch1.png
new file mode 100755
index 0000000..7c5129d
Binary files /dev/null and b/odex30_base/branch/static/description/branch1.png differ
diff --git a/odex30_base/branch/static/description/branch10.png b/odex30_base/branch/static/description/branch10.png
new file mode 100755
index 0000000..0c3685a
Binary files /dev/null and b/odex30_base/branch/static/description/branch10.png differ
diff --git a/odex30_base/branch/static/description/branch11.png b/odex30_base/branch/static/description/branch11.png
new file mode 100755
index 0000000..e9dc415
Binary files /dev/null and b/odex30_base/branch/static/description/branch11.png differ
diff --git a/odex30_base/branch/static/description/branch12.png b/odex30_base/branch/static/description/branch12.png
new file mode 100755
index 0000000..61cee96
Binary files /dev/null and b/odex30_base/branch/static/description/branch12.png differ
diff --git a/odex30_base/branch/static/description/branch13.png b/odex30_base/branch/static/description/branch13.png
new file mode 100755
index 0000000..0c83820
Binary files /dev/null and b/odex30_base/branch/static/description/branch13.png differ
diff --git a/odex30_base/branch/static/description/branch14.png b/odex30_base/branch/static/description/branch14.png
new file mode 100755
index 0000000..d3d367a
Binary files /dev/null and b/odex30_base/branch/static/description/branch14.png differ
diff --git a/odex30_base/branch/static/description/branch15.png b/odex30_base/branch/static/description/branch15.png
new file mode 100755
index 0000000..6e2cc6e
Binary files /dev/null and b/odex30_base/branch/static/description/branch15.png differ
diff --git a/odex30_base/branch/static/description/branch16.png b/odex30_base/branch/static/description/branch16.png
new file mode 100755
index 0000000..6bb5232
Binary files /dev/null and b/odex30_base/branch/static/description/branch16.png differ
diff --git a/odex30_base/branch/static/description/branch17.png b/odex30_base/branch/static/description/branch17.png
new file mode 100755
index 0000000..38e76af
Binary files /dev/null and b/odex30_base/branch/static/description/branch17.png differ
diff --git a/odex30_base/branch/static/description/branch18.png b/odex30_base/branch/static/description/branch18.png
new file mode 100755
index 0000000..f6304b0
Binary files /dev/null and b/odex30_base/branch/static/description/branch18.png differ
diff --git a/odex30_base/branch/static/description/branch19.png b/odex30_base/branch/static/description/branch19.png
new file mode 100755
index 0000000..3a153d8
Binary files /dev/null and b/odex30_base/branch/static/description/branch19.png differ
diff --git a/odex30_base/branch/static/description/branch2.png b/odex30_base/branch/static/description/branch2.png
new file mode 100755
index 0000000..4d6e55a
Binary files /dev/null and b/odex30_base/branch/static/description/branch2.png differ
diff --git a/odex30_base/branch/static/description/branch20.png b/odex30_base/branch/static/description/branch20.png
new file mode 100755
index 0000000..f617f0d
Binary files /dev/null and b/odex30_base/branch/static/description/branch20.png differ
diff --git a/odex30_base/branch/static/description/branch21.png b/odex30_base/branch/static/description/branch21.png
new file mode 100755
index 0000000..9ceb4e0
Binary files /dev/null and b/odex30_base/branch/static/description/branch21.png differ
diff --git a/odex30_base/branch/static/description/branch22.png b/odex30_base/branch/static/description/branch22.png
new file mode 100755
index 0000000..b5fc003
Binary files /dev/null and b/odex30_base/branch/static/description/branch22.png differ
diff --git a/odex30_base/branch/static/description/branch23.png b/odex30_base/branch/static/description/branch23.png
new file mode 100755
index 0000000..23ccdf0
Binary files /dev/null and b/odex30_base/branch/static/description/branch23.png differ
diff --git a/odex30_base/branch/static/description/branch24.png b/odex30_base/branch/static/description/branch24.png
new file mode 100755
index 0000000..93b2fdb
Binary files /dev/null and b/odex30_base/branch/static/description/branch24.png differ
diff --git a/odex30_base/branch/static/description/branch25.png b/odex30_base/branch/static/description/branch25.png
new file mode 100755
index 0000000..9038e2a
Binary files /dev/null and b/odex30_base/branch/static/description/branch25.png differ
diff --git a/odex30_base/branch/static/description/branch26.png b/odex30_base/branch/static/description/branch26.png
new file mode 100755
index 0000000..f83a3f3
Binary files /dev/null and b/odex30_base/branch/static/description/branch26.png differ
diff --git a/odex30_base/branch/static/description/branch3.png b/odex30_base/branch/static/description/branch3.png
new file mode 100755
index 0000000..cf207e5
Binary files /dev/null and b/odex30_base/branch/static/description/branch3.png differ
diff --git a/odex30_base/branch/static/description/branch4.png b/odex30_base/branch/static/description/branch4.png
new file mode 100755
index 0000000..934d30b
Binary files /dev/null and b/odex30_base/branch/static/description/branch4.png differ
diff --git a/odex30_base/branch/static/description/branch5.png b/odex30_base/branch/static/description/branch5.png
new file mode 100755
index 0000000..5ed447a
Binary files /dev/null and b/odex30_base/branch/static/description/branch5.png differ
diff --git a/odex30_base/branch/static/description/branch6.png b/odex30_base/branch/static/description/branch6.png
new file mode 100755
index 0000000..3daec00
Binary files /dev/null and b/odex30_base/branch/static/description/branch6.png differ
diff --git a/odex30_base/branch/static/description/branch7.png b/odex30_base/branch/static/description/branch7.png
new file mode 100755
index 0000000..8ee33f6
Binary files /dev/null and b/odex30_base/branch/static/description/branch7.png differ
diff --git a/odex30_base/branch/static/description/branch8.png b/odex30_base/branch/static/description/branch8.png
new file mode 100755
index 0000000..71c1fb1
Binary files /dev/null and b/odex30_base/branch/static/description/branch8.png differ
diff --git a/odex30_base/branch/static/description/branch9.png b/odex30_base/branch/static/description/branch9.png
new file mode 100755
index 0000000..558952e
Binary files /dev/null and b/odex30_base/branch/static/description/branch9.png differ
diff --git a/odex30_base/branch/static/src/js/branch_service.js b/odex30_base/branch/static/src/js/branch_service.js
new file mode 100755
index 0000000..33874dc
--- /dev/null
+++ b/odex30_base/branch/static/src/js/branch_service.js
@@ -0,0 +1,185 @@
+/** @odoo-module **/
+
+import { browser } from "@web/core/browser/browser";
+import { registry } from "@web/core/registry";
+import { session } from "@web/session";
+import { UPDATE_METHODS } from "@web/core/orm_service";
+import { cookie } from "@web/core/browser/cookie";
+import { jsonrpc } from "@web/core/network/rpc";
+
+const CIDS_HASH_SEPARATOR = "-";
+const BIDS_HASH_SEPARATOR = "-";
+
+function parseCompanyIds(cids, separator = ",") {
+ if (typeof cids === "string") {
+ return cids.split(separator).map(Number);
+ } else if (typeof cids === "number") {
+ return [cids];
+ }
+ return [];
+}
+
+function parseBranchIds(bids, separator = ",") {
+ if (typeof bids === "string") {
+ return bids.split(separator).map(Number);
+ } else if (typeof bids === "number") {
+ return [bids];
+ }
+ return [];
+}
+
+function formatBranchIds(bids, separator = ",") {
+ return bids.join(separator);
+}
+
+function computeActiveBranchIds(allowedBranches, bids) {
+ let activeBranchIds = bids || [];
+ activeBranchIds = activeBranchIds.filter(
+ (id) => id in allowedBranches
+ );
+ if (!activeBranchIds.length) {
+ if (allowedBranches) {
+ activeBranchIds = [Object.values(allowedBranches)[0].id];
+ } else {
+ activeBranchIds = [session.user_branches.current_branch];
+ }
+ }
+ return activeBranchIds;
+}
+
+function getCompanyIdsFromBrowser(hash) {
+ let cids;
+ if ("cids" in hash) {
+ // backward compatibility s.t. old urls (still using "," as separator) keep working
+ // deprecated as of 17.0
+ let separator = CIDS_HASH_SEPARATOR;
+ if (typeof hash.cids === "string" && !hash.cids.includes(CIDS_HASH_SEPARATOR)) {
+ separator = ",";
+ }
+ cids = parseCompanyIds(hash.cids, separator);
+ } else if (cookie.get("cids")) {
+ cids = parseCompanyIds(cookie.get("cids"));
+ }
+ return cids || [];
+}
+
+function getBranchIdsFromBrowser(hash) {
+ let bids;
+ if ("bids" in hash) {
+ // backward compatibility s.t. old urls (still using "," as separator) keep working
+ // deprecated as of 17.0
+ let separator = BIDS_HASH_SEPARATOR;
+ if (typeof hash.bids === "string" && !hash.bids.includes(BIDS_HASH_SEPARATOR)) {
+ separator = ",";
+ }
+ bids = parseBranchIds(hash.bids, separator);
+ } else if (cookie.get("bids")) {
+ bids = parseBranchIds(cookie.get("bids"));
+ }
+ return bids || [];
+}
+
+const errorHandlerRegistry = registry.category("error_handlers");
+function accessErrorHandler(env, error, originalError) {
+ const router = env.services.router;
+ const hash = router.current.hash;
+ if (!hash._Branch_switching) {
+ return false;
+ }
+ if (originalError?.exceptionName === "odoo.exceptions.AccessError") {
+ const { model, id, view_type } = hash;
+ if (!model || !id || view_type !== "form") {
+ return false;
+ }
+ router.pushState({ view_type: undefined });
+
+ browser.setTimeout(() => {
+ // Force the WebClient to reload the state contained in the hash.
+ env.bus.trigger("ROUTE_CHANGE");
+ });
+ if (error.event) {
+ error.event.preventDefault();
+ }
+ return true;
+ }
+ return false;
+}
+
+export const BranchService = {
+ dependencies: ["user", "router", "action"],
+ start(env, { user, router, action }) {
+ // Push an error handler in the registry. It needs to be before "rpcErrorHandler", which
+ // has a sequence of 97. The default sequence of registry is 50.
+ errorHandlerRegistry.add("accessErrorHandlerBranches", accessErrorHandler);
+
+ let cids = getCompanyIdsFromBrowser(router.current.hash);
+ const allowedBranches = Object.fromEntries(
+ Object.entries(session.user_branches.allowed_branches).filter(([k,v]) => cids.includes(v.company))
+ );
+ const allowedBranchesWithAncestors = {
+ ...allowedBranches,
+ };
+ const activeBranchIds = computeActiveBranchIds(
+ allowedBranches, getBranchIdsFromBrowser(router.current.hash)
+ );
+
+ // update browser data
+ const bidsHash = formatBranchIds(activeBranchIds, BIDS_HASH_SEPARATOR);
+ router.replaceState({ bids: bidsHash }, { lock: true });
+ cookie.set("bids", formatBranchIds(activeBranchIds));
+ user.updateContext({ allowed_branch_ids: activeBranchIds });
+
+ // reload the page if changes are being done to `res.branch`
+ env.bus.addEventListener("RPC:RESPONSE", (ev) => {
+ const { data, error } = ev.detail;
+ const { model, method } = data.params;
+ if (!error && model === "res.branch" && UPDATE_METHODS.includes(method)) {
+ if (!browser.localStorage.getItem("running_tour")) {
+ action.doAction("reload_context");
+ }
+ }
+ });
+
+ return {
+ allowedBranches,
+ allowedBranchesWithAncestors,
+
+ get activeBranchIds() {
+ return activeBranchIds.slice();
+ },
+
+ get currentBranch() {
+ return allowedBranches[activeBranchIds[0]];
+ },
+
+ getBranch(BranchId) {
+ return allowedBranchesWithAncestors[BranchId];
+ },
+
+ /**
+ * @param {Array<>} BranchIds - List of branches to log into
+ */
+ setBranches(BranchIds) {
+ const newBranchIds = BranchIds.length ? BranchIds : [activeBranchIds[0]];
+ function addBranches(BranchIds) {
+ for (const BranchId of BranchIds) {
+ if (!newBranchIds.includes(BranchId)) {
+ newBranchIds.push(BranchId);
+ }
+ }
+ }
+ const bidsHash = formatBranchIds(newBranchIds, BIDS_HASH_SEPARATOR);
+ router.pushState({ bids: bidsHash }, { lock: true });
+ router.pushState({ _Branch_switching: true });
+ cookie.set("bids", formatBranchIds(newBranchIds));
+ jsonrpc('/set_branch',{
+ BranchID: newBranchIds[0],
+ })
+ browser.setTimeout(() => browser.location.reload()); // history.pushState is a little async
+ },
+ };
+ },
+};
+if (session.display_switch_branch_menu) {
+ registry.category("services").add("Branch", BranchService);
+}
diff --git a/odex30_base/branch/views/account_bank_statement.xml b/odex30_base/branch/views/account_bank_statement.xml
new file mode 100644
index 0000000..41903d8
--- /dev/null
+++ b/odex30_base/branch/views/account_bank_statement.xml
@@ -0,0 +1,13 @@
+
+
+
+ view.bank.statement.form.inherit.branch
+ account.bank.statement
+
+
+
+
+
+
+
+
diff --git a/odex30_base/branch/views/account_move.xml b/odex30_base/branch/views/account_move.xml
new file mode 100644
index 0000000..b5439eb
--- /dev/null
+++ b/odex30_base/branch/views/account_move.xml
@@ -0,0 +1,99 @@
+
+
+
+
+ account.move.inherit.tree
+ account.move
+
+
+
+
+
+
+
+
+
+ account.move.inherit.tree.invoice
+ account.move
+
+
+
+
+
+
+
+
+
+ account.payment.inherit.tree
+ account.payment
+
+
+
+
+
+
+
+
+
+ account.move.line.inherit.form
+ account.move.line
+
+
+
+
+
+
+
+
+
+ account.move.line.inherit.tree
+ account.move.line
+
+
+
+
+
+
+
+
+
+ view.move.form.inherit.branch
+ account.move
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ view.move.line.tree.inherit.branch
+ account.move.line
+
+
+
+
+
+
+
+
+
+ move.line.filter.inherit.branch
+ account.move.line
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/odex30_base/branch/views/account_payment.xml b/odex30_base/branch/views/account_payment.xml
new file mode 100644
index 0000000..c9b059a
--- /dev/null
+++ b/odex30_base/branch/views/account_payment.xml
@@ -0,0 +1,27 @@
+
+
+
+
+ view.account.payment.invoice.form.inherit.branch
+ account.payment
+
+
+
+
+
+
+
+
+
+ view.account.payment.register.form.inherit.branch
+ account.payment.register
+
+
+
+
+
+
+
+
+
+
diff --git a/odex30_base/branch/views/inherited_account_bank_statement.xml b/odex30_base/branch/views/inherited_account_bank_statement.xml
deleted file mode 100644
index 4bd5c38..0000000
--- a/odex30_base/branch/views/inherited_account_bank_statement.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-
- view.bank.statement.form.inherit.branch
- account.bank.statement
-
-
-
-
-
-
-
-
-
-
-
-
- {'branch_id' : branch_id}
-
-
-
-
-
-
diff --git a/odex30_base/branch/views/inherited_account_invoice.xml b/odex30_base/branch/views/inherited_account_invoice.xml
deleted file mode 100644
index 8610e1e..0000000
--- a/odex30_base/branch/views/inherited_account_invoice.xml
+++ /dev/null
@@ -1,107 +0,0 @@
-
-
-
-
-
- account.move.inherit.tree
- account.move
-
-
-
-
-
-
-
-
-
- account.move.inherit.tree1
- account.move
-
-
-
-
-
-
-
-
-
- account.payment.inherit.tree
- account.payment
-
-
-
-
-
-
-
-
-
- account.move.line.inherit.form
- account.move.line
-
-
-
-
-
-
-
-
-
- account.move.line.inherit.tree2
- account.move.line
-
-
-
-
-
-
-
-
-
-
- view.move.form.inherit.branch
- account.move
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- view.move.line.tree.inherit.branch
- account.move.line
-
-
-
-
-
-
-
-
-
- move.line.filter.inherit.branch
- account.move.line
-
-
-
-
-
-
-
-
-
-
diff --git a/odex30_base/branch/views/inherited_product.xml b/odex30_base/branch/views/inherited_product.xml
deleted file mode 100644
index 8f42537..0000000
--- a/odex30_base/branch/views/inherited_product.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
- product_extended.product.form.branch
- product.template
-
-
-
-
-
-
-
-
-
- product.product.view.form.branch
- product.product
-
-
-
-
-
-
-
-
-
diff --git a/odex30_base/branch/views/inherited_res_users.xml b/odex30_base/branch/views/inherited_res_users.xml
deleted file mode 100644
index d63a310..0000000
--- a/odex30_base/branch/views/inherited_res_users.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-
-
-
-
-
- view.users.form.inherit.branch
- res.users
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- res.user.preference.form.extended
- res.users
-
-
-
-
-
-
-
-
-
diff --git a/odex30_base/branch/views/inherited_sale_order.xml b/odex30_base/branch/views/inherited_sale_order.xml
deleted file mode 100644
index 56fe6d1..0000000
--- a/odex30_base/branch/views/inherited_sale_order.xml
+++ /dev/null
@@ -1,55 +0,0 @@
-
-
-
-
-
- view.order.form.inherit.branch
- sale.order
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- view.sales.order.filter.inherit.branch
- sale.order
-
-
-
-
-
-
-
-
-
- sale.order.inherit.tree
- sale.order
-
-
-
-
-
-
-
-
-
- sale.order.inherit.tree1
- sale.order
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/odex30_base/branch/views/inherited_stock_inventory.xml b/odex30_base/branch/views/inherited_stock_inventory.xml
deleted file mode 100644
index 7af7e10..0000000
--- a/odex30_base/branch/views/inherited_stock_inventory.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
- view.stock.inventory.adjustment.form.inherit.branch
- stock.inventory.adjustment.name
-
-
-
-
-
-
-
-
-
diff --git a/odex30_base/branch/views/inherited_stock_picking.xml b/odex30_base/branch/views/inherited_stock_picking.xml
deleted file mode 100644
index 1a69385..0000000
--- a/odex30_base/branch/views/inherited_stock_picking.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
-
- view.picking.form.inherit.branch
- stock.picking
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/odex30_base/branch/views/inherited_stock_warehouse.xml b/odex30_base/branch/views/inherited_stock_warehouse.xml
deleted file mode 100644
index 6bb83d3..0000000
--- a/odex30_base/branch/views/inherited_stock_warehouse.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
- view.warehouse.inherit.branch
- stock.warehouse
-
-
-
-
-
-
-
-
-
- view.stock.picking.type.inherit.branch
- stock.picking.type
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/odex30_base/branch/views/product.xml b/odex30_base/branch/views/product.xml
new file mode 100644
index 0000000..cc73298
--- /dev/null
+++ b/odex30_base/branch/views/product.xml
@@ -0,0 +1,13 @@
+
+
+
+ product.product.form.branch
+ product.template
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/odex30_base/branch/views/inherited_purchase_order.xml b/odex30_base/branch/views/purchase_order.xml
similarity index 82%
rename from odex30_base/branch/views/inherited_purchase_order.xml
rename to odex30_base/branch/views/purchase_order.xml
index d7b1ce9..99a2ad7 100644
--- a/odex30_base/branch/views/inherited_purchase_order.xml
+++ b/odex30_base/branch/views/purchase_order.xml
@@ -6,11 +6,8 @@
purchase.order
-
-
-
-
- {'branch_id' : branch_id}
+
+
@@ -21,7 +18,7 @@
-
+
diff --git a/odex30_base/branch/views/res_branch_view.xml b/odex30_base/branch/views/res_branch_view.xml
index 74b0186..767e658 100644
--- a/odex30_base/branch/views/res_branch_view.xml
+++ b/odex30_base/branch/views/res_branch_view.xml
@@ -50,7 +50,7 @@
-
+
diff --git a/odex30_base/branch/views/inherited_partner.xml b/odex30_base/branch/views/res_partner.xml
similarity index 100%
rename from odex30_base/branch/views/inherited_partner.xml
rename to odex30_base/branch/views/res_partner.xml
diff --git a/odex30_base/branch/views/res_users.xml b/odex30_base/branch/views/res_users.xml
new file mode 100644
index 0000000..28bced4
--- /dev/null
+++ b/odex30_base/branch/views/res_users.xml
@@ -0,0 +1,30 @@
+
+
+
+ view.users.form.inherit.branch
+ res.users
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ res.user.preference.form.extended
+ res.users
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/odex30_base/branch/views/sale_order.xml b/odex30_base/branch/views/sale_order.xml
new file mode 100644
index 0000000..e05e027
--- /dev/null
+++ b/odex30_base/branch/views/sale_order.xml
@@ -0,0 +1,40 @@
+
+
+
+
+ view.order.form.inherit.branch
+ sale.order
+
+
+
+
+
+
+
+
+
+
+
+
+
+ view.sales.order.filter.inherit.branch
+ sale.order
+
+
+
+
+
+
+
+
+
+ sale.order.inherit.tree
+ sale.order
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/odex30_base/branch/views/inherited_stock_location.xml b/odex30_base/branch/views/stock_location.xml
similarity index 100%
rename from odex30_base/branch/views/inherited_stock_location.xml
rename to odex30_base/branch/views/stock_location.xml
diff --git a/odex30_base/branch/views/inherited_stock_move.xml b/odex30_base/branch/views/stock_move.xml
similarity index 91%
rename from odex30_base/branch/views/inherited_stock_move.xml
rename to odex30_base/branch/views/stock_move.xml
index e7038e7..5c7f2c1 100644
--- a/odex30_base/branch/views/inherited_stock_move.xml
+++ b/odex30_base/branch/views/stock_move.xml
@@ -8,7 +8,7 @@
-
+
diff --git a/odex30_base/branch/views/stock_picking.xml b/odex30_base/branch/views/stock_picking.xml
new file mode 100644
index 0000000..327a90e
--- /dev/null
+++ b/odex30_base/branch/views/stock_picking.xml
@@ -0,0 +1,13 @@
+
+
+
+ view.picking.form.inherit.branch
+ stock.picking
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/odex30_base/branch/views/stock_picking_type.xml b/odex30_base/branch/views/stock_picking_type.xml
new file mode 100644
index 0000000..b6feaac
--- /dev/null
+++ b/odex30_base/branch/views/stock_picking_type.xml
@@ -0,0 +1,13 @@
+
+
+
+ view.stock.picking.type.inherit.branch
+ stock.picking.type
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/odex30_base/branch/views/stock_warehouse.xml b/odex30_base/branch/views/stock_warehouse.xml
new file mode 100644
index 0000000..0019916
--- /dev/null
+++ b/odex30_base/branch/views/stock_warehouse.xml
@@ -0,0 +1,13 @@
+
+
+
+ view.warehouse.inherit.branch
+ stock.warehouse
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/odex30_base/branch/wizard/__init__.py b/odex30_base/branch/wizard/__init__.py
index 46068eb..8df6b57 100644
--- a/odex30_base/branch/wizard/__init__.py
+++ b/odex30_base/branch/wizard/__init__.py
@@ -1,5 +1,4 @@
# Part of BrowseInfo. See LICENSE file for full copyright and licensing details.
-from . import inherited_sale_advance_payment_inv
+from . import account_payment_register
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/odex30_base/branch/wizard/account_payment_register.py b/odex30_base/branch/wizard/account_payment_register.py
new file mode 100644
index 0000000..575d7d9
--- /dev/null
+++ b/odex30_base/branch/wizard/account_payment_register.py
@@ -0,0 +1,23 @@
+# Part of BrowseInfo. See LICENSE file for full copyright and licensing details.
+
+from odoo import api, fields, models, _
+
+
+class AccountPaymentRegister(models.TransientModel):
+ _inherit = 'account.payment.register'
+
+ branch_id = fields.Many2one('res.branch')
+
+ @api.model
+ def default_get(self, fields):
+ rec = super(AccountPaymentRegister, self).default_get(fields)
+ invoice_defaults = self.env['account.move'].browse(self._context.get('active_ids', []))
+ if invoice_defaults and len(invoice_defaults) == 1:
+ rec['branch_id'] = invoice_defaults.branch_id.id
+ return rec
+
+ def _create_payment_vals_from_wizard(self, batch_result):
+ payment_vals = super(AccountPaymentRegister, self)._create_payment_vals_from_wizard(batch_result)
+ payment_vals['branch_id'] = self.branch_id.id
+ return payment_vals
+
diff --git a/odex30_base/branch/wizard/inherited_account_payment.xml b/odex30_base/branch/wizard/inherited_account_payment.xml
deleted file mode 100644
index bbea15b..0000000
--- a/odex30_base/branch/wizard/inherited_account_payment.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-
-
-
-
-
-
- view.account.payment.invoice.form.inherit.branch
- account.payment
-
-
-
-
-
-
-
-
-
-
-
- view.account.payment.register.form.inherit.branch
- account.payment.register
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/odex30_base/branch/wizard/inherited_sale_advance_payment_inv.py b/odex30_base/branch/wizard/inherited_sale_advance_payment_inv.py
deleted file mode 100644
index 2ddd9e0..0000000
--- a/odex30_base/branch/wizard/inherited_sale_advance_payment_inv.py
+++ /dev/null
@@ -1,47 +0,0 @@
-# Part of BrowseInfo. See LICENSE file for full copyright and licensing details.
-
-from odoo import api, fields, models, _
-from odoo.exceptions import UserError
-
-
-class SaleAdvancePaymentInv(models.TransientModel):
- _inherit = 'sale.advance.payment.inv'
-
-
- def _create_invoice(self, order, so_line, amount):
- result = super(SaleAdvancePaymentInv, self)._create_invoice(order, so_line, amount)
-
- branch_id = False
-
- if order.branch_id:
- branch_id = order.branch_id.id
- elif self.env.user.branch_id:
- branch_id = self.env.user.branch_id.id
-
- result.write({
- 'branch_id' : branch_id
- })
-
- return result
-
-class AccountPaymentRegisterInv(models.TransientModel):
- _inherit = 'account.payment.register'
-
- @api.model
- def default_get(self, fields):
- rec = super(AccountPaymentRegisterInv, self).default_get(fields)
- invoice_defaults = self.env['account.move'].browse(self._context.get('active_ids', []))
- if invoice_defaults and len(invoice_defaults) == 1:
- rec['branch_id'] = invoice_defaults.branch_id.id
- return rec
-
- branch_id = fields.Many2one('res.branch')
-
- @api.onchange('branch_id')
- def _onchange_branch_id(self):
- selected_brach = self.branch_id
- if selected_brach:
- user_id = self.env.user
- user_branch = user_id.sudo().branch_id
- if user_branch and user_branch.id != selected_brach.id:
- raise UserError("Please select active branch only. Other may create the Multi branch issue. \n\ne.g: If you wish to add other branch then Switch branch from the header and set that.")
\ No newline at end of file
diff --git a/odex30_base/custom_report_layout/__init__.py b/odex30_base/custom_report_layout/__init__.py
new file mode 100644
index 0000000..5305644
--- /dev/null
+++ b/odex30_base/custom_report_layout/__init__.py
@@ -0,0 +1,3 @@
+# -*- coding: utf-8 -*-
+
+from . import models
\ No newline at end of file
diff --git a/odex30_base/custom_report_layout/__manifest__.py b/odex30_base/custom_report_layout/__manifest__.py
new file mode 100644
index 0000000..b2dd550
--- /dev/null
+++ b/odex30_base/custom_report_layout/__manifest__.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+{
+ 'name': "Custom Report Layout",
+ 'version': '18.0.1.0.0', # تم تحديث النسخة لأودو 18
+ 'summary': 'A module to configure report header and footer',
+ 'sequence': -100,
+ 'description': 'A module to configure report header and footer manually from company form',
+ 'author': "Ismail Mohamedi",
+ 'website': "https://www.linkedin.com/in/ismail-mohamedi-605537179",
+ 'category': 'Odex25-base',
+ 'license': 'LGPL-3',
+ 'depends': ['base'], # تأكد وجود الحزم المطلوبة لأودو 18
+ 'data': [
+ 'report/base_document_layout.xml',
+ 'views/views.xml',
+ ],
+ 'images': ['static/description/header_footer.png'],
+ 'installable': True,
+ 'application': True,
+ 'auto_install': False,
+}
diff --git a/odex30_base/custom_report_layout/models/__init__.py b/odex30_base/custom_report_layout/models/__init__.py
new file mode 100644
index 0000000..5305644
--- /dev/null
+++ b/odex30_base/custom_report_layout/models/__init__.py
@@ -0,0 +1,3 @@
+# -*- coding: utf-8 -*-
+
+from . import models
\ No newline at end of file
diff --git a/odex30_base/custom_report_layout/models/models.py b/odex30_base/custom_report_layout/models/models.py
new file mode 100644
index 0000000..707094a
--- /dev/null
+++ b/odex30_base/custom_report_layout/models/models.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+from odoo import models, fields, api, _
+
+
+class ResCompany(models.Model):
+ """"""
+ _inherit = "res.company"
+
+ header = fields.Image("Header")
+ footer = fields.Image("Footer")
+ header_width = fields.Char("Header Width", default="1000")
+ header_height = fields.Char("Header height", default="150")
+ footer_width = fields.Char("Footer Width", default="1000")
+ footer_height = fields.Char("Footer height", default="100")
\ No newline at end of file
diff --git a/odex30_base/custom_report_layout/report/base_document_layout.xml b/odex30_base/custom_report_layout/report/base_document_layout.xml
new file mode 100644
index 0000000..4fe8cf1
--- /dev/null
+++ b/odex30_base/custom_report_layout/report/base_document_layout.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/odex30_base/custom_report_layout/static/description/header_footer.png b/odex30_base/custom_report_layout/static/description/header_footer.png
new file mode 100644
index 0000000..76937de
Binary files /dev/null and b/odex30_base/custom_report_layout/static/description/header_footer.png differ
diff --git a/odex30_base/custom_report_layout/views/views.xml b/odex30_base/custom_report_layout/views/views.xml
new file mode 100644
index 0000000..2b9c748
--- /dev/null
+++ b/odex30_base/custom_report_layout/views/views.xml
@@ -0,0 +1,28 @@
+
+
+
+ res.company.form.layout.inherit
+ res.company
+
+
+
+
+
+
+
+ ,
+
+
+
+
+
+ ,
+
+
+
+
+
+
+
diff --git a/odex30_base/date_range/README.rst b/odex30_base/date_range/README.rst
new file mode 100644
index 0000000..f303304
--- /dev/null
+++ b/odex30_base/date_range/README.rst
@@ -0,0 +1,180 @@
+==========
+Date Range
+==========
+
+.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ !! This file is generated by oca-gen-addon-readme !!
+ !! changes will be overwritten. !!
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+.. |badge1| image:: https://img.shields.io/badge/maturity-Mature-brightgreen.png
+ :target: https://odoo-community.org/page/development-status
+ :alt: Mature
+.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
+ :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
+ :alt: License: AGPL-3
+.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fserver--ux-lightgray.png?logo=github
+ :target: https://github.com/OCA/server-ux/tree/14.0/date_range
+ :alt: OCA/server-ux
+.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
+ :target: https://translation.odoo-community.org/projects/server-ux-14-0/server-ux-14-0-date_range
+ :alt: Translate me on Weblate
+.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
+ :target: https://runbot.odoo-community.org/runbot/250/14.0
+ :alt: Try me on Runbot
+
+|badge1| |badge2| |badge3| |badge4| |badge5|
+
+This module lets you define global date ranges that can be used to filter
+your values in tree views.
+
+It also provides a mixin model for developers that extends the model's search
+view so that date ranges can be search as any relational field.
+
+**Table of contents**
+
+.. contents::
+ :local:
+
+Installation
+============
+
+The addon use the daterange method from postgres. This method is supported as of postgresql 9.2
+
+Configuration
+=============
+
+For regular usage, see `Usage` below. This section is to clarify optional
+functionality to developers.
+
+To configure a model to use the Many2one style search field, make the model
+inherit from `date.range.search.mixin`:
+
+.. code-block::
+
+ class AccountMove(models.Model):
+ _name = "account.move"
+ _inherit = ["account.move", "date.range.search.mixin"]
+
+This will make a `Period` field show up in the search view:
+
+ .. figure:: https://raw.githubusercontent.com/OCA/server-tools/12.0/date_range/static/description/date_range_many2one_search_field.png
+ :scale: 80 %
+ :alt: Date range Many2one search field
+
+By default, the mixin works on the `date` field. If you want the mixin to work
+on a field with a different name, you can set a property on your model:
+
+.. code-block::
+
+ _date_range_search_field = "invoice_date"
+
+Usage
+=====
+
+To configure this module, you need to:
+
+* Go to Settings > Technical > Date ranges > Date Range Types where
+ you can create types of date ranges.
+
+ .. figure:: https://raw.githubusercontent.com/OCA/server-tools/14.0/date_range/static/description/date_range_type_create.png
+ :scale: 80 %
+ :alt: Create a type of date range
+
+* Go to Settings > Technical > Date ranges > Date Ranges where
+ you can create date ranges.
+
+ .. figure:: https://raw.githubusercontent.com/OCA/server-tools/14.0/date_range/static/description/date_range_create.png
+ :scale: 80 %
+ :alt: Date range creation
+
+ It's also possible to launch a wizard from the 'Generate Date Ranges' menu.
+
+ .. figure:: https://raw.githubusercontent.com/OCA/server-tools/14.0/date_range/static/description/date_range_wizard.png
+ :scale: 80 %
+ :alt: Date range wizard
+
+ The wizard is useful to generate recurring periods. Set an end date or enter the number of ranges to create.
+
+ .. figure:: https://raw.githubusercontent.com/OCA/server-tools/14.0/date_range/static/description/date_range_wizard_result.png
+ :scale: 80 %
+ :alt: Date range wizard result
+
+* Your date ranges are now available in the search filter for any date or datetime fields
+
+ Date range types are proposed as a filter operator
+
+ .. figure:: https://raw.githubusercontent.com/OCA/server-tools/14.0/date_range/static/description/date_range_type_as_filter.png
+ :scale: 80 %
+ :alt: Date range type available as filter operator
+
+ Once a type is selected, date ranges of this type are porposed as a filter value
+
+ .. figure:: https://raw.githubusercontent.com/OCA/server-tools/14.0/date_range/static/description/date_range_as_filter.png
+ :scale: 80 %
+ :alt: Date range as filter value
+
+ And the dates specified into the date range are used to filter your result.
+
+ .. figure:: https://raw.githubusercontent.com/OCA/server-tools/14.0/date_range/static/description/date_range_as_filter_result.png
+ :scale: 80 %
+ :alt: Date range as filter result
+
+* You can configure date range types with default values for the generation wizard on the `Generation` tab.
+ In the same tab you can also configure date range types for auto-generation. New ranges for types configured for this are generated by a scheduled task that runs daily.
+
+ .. figure:: https://raw.githubusercontent.com/OCA/server-tools/14.0/date_range/static/description/date_range_type_autogeneration.png
+ :scale: 80 %
+ :alt: Configure a date range for auto-generaton
+
+Bug Tracker
+===========
+
+Bugs are tracked on `GitHub Issues `_.
+In case of trouble, please check there if your issue has already been reported.
+If you spotted it first, help us smashing it by providing a detailed and welcomed
+`feedback `_.
+
+Do not contact contributors directly about support or help with technical issues.
+
+Credits
+=======
+
+Authors
+~~~~~~~
+
+* ACSONE SA/NV
+
+Contributors
+~~~~~~~~~~~~
+
+* Laurent Mignon
+* Alexis de Lattre
+* Miquel Raïch
+* Andrea Stirpe
+* Stefan Rijnhart
+
+Maintainers
+~~~~~~~~~~~
+
+This module is maintained by the OCA.
+
+.. image:: https://odoo-community.org/logo.png
+ :alt: Odoo Community Association
+ :target: https://odoo-community.org
+
+OCA, or the Odoo Community Association, is a nonprofit organization whose
+mission is to support the collaborative development of Odoo features and
+promote its widespread use.
+
+.. |maintainer-lmignon| image:: https://github.com/lmignon.png?size=40px
+ :target: https://github.com/lmignon
+ :alt: lmignon
+
+Current `maintainer `__:
+
+|maintainer-lmignon|
+
+This module is part of the `OCA/server-ux `_ project on GitHub.
+
+You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
diff --git a/odex30_base/date_range/__init__.py b/odex30_base/date_range/__init__.py
new file mode 100644
index 0000000..4d7a49b
--- /dev/null
+++ b/odex30_base/date_range/__init__.py
@@ -0,0 +1,4 @@
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from . import models
+from . import wizard
diff --git a/odex30_base/date_range/__manifest__.py b/odex30_base/date_range/__manifest__.py
new file mode 100644
index 0000000..991c0a0
--- /dev/null
+++ b/odex30_base/date_range/__manifest__.py
@@ -0,0 +1,28 @@
+# Copyright 2016 ACSONE SA/NV ()
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+{
+ "name": "Date Range",
+ "summary": "Manage all kind of date range",
+ "version": "18.0.2.1",
+ "category": "Odex30-base",
+ "website": "https://github.com/OCA/server-ux",
+ "author": "ACSONE SA/NV, Odoo Community Association (OCA)",
+ "license": "AGPL-3",
+ "installable": True,
+ "depends": [
+ "web",
+ ],
+ # odoo_test_helper is needed for the tests
+ "data": [
+ "data/ir_cron_data.xml",
+ "security/ir.model.access.csv",
+ "security/date_range_security.xml",
+ "views/assets.xml",
+ "views/date_range_view.xml",
+ "wizard/date_range_generator.xml",
+ ],
+ "qweb": ["static/src/xml/date_range.xml"],
+ "development_status": "Mature",
+ "maintainers": ["lmignon"],
+
+}
diff --git a/odex30_base/date_range/data/ir_cron_data.xml b/odex30_base/date_range/data/ir_cron_data.xml
new file mode 100644
index 0000000..b7127a7
--- /dev/null
+++ b/odex30_base/date_range/data/ir_cron_data.xml
@@ -0,0 +1,18 @@
+
+
+
+
+ Auto-generate date ranges
+
+ code
+ model.autogenerate_ranges()
+
+
+
+ 1
+ days
+ True
+
+ 5
+
+
diff --git a/odex30_base/date_range/i18n/am.po b/odex30_base/date_range/i18n/am.po
new file mode 100644
index 0000000..0943a0c
--- /dev/null
+++ b/odex30_base/date_range/i18n/am.po
@@ -0,0 +1,451 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+msgid ""
+msgstr ""
+"Project-Id-Version: server-tools (9.0)\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2016-09-10 02:53+0000\n"
+"PO-Revision-Date: 2016-04-29 09:59+0000\n"
+"Last-Translator: <>\n"
+"Language-Team: Amharic (http://www.transifex.com/oca/OCA-server-tools-9-0/"
+"language/am/)\n"
+"Language: am\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Cancelar"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Creado por"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Creado en"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Última actualización por"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Última actualización en"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+msgid "Type Name"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/ar.po b/odex30_base/date_range/i18n/ar.po
new file mode 100644
index 0000000..a296c7d
--- /dev/null
+++ b/odex30_base/date_range/i18n/ar.po
@@ -0,0 +1,459 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2018-07-01 04:01+0000\n"
+"Last-Translator: Osoul \n"
+"Language-Team: Arabic (https://www.transifex.com/oca/teams/23907/ar/)\n"
+"Language: ar\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 "
+"&& n%100<=10 ? 3 : n%100>=11 ? 4 : 5;\n"
+"X-Generator: Weblate 3.0.1\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr "%s ليست فترة سليمة (%s > %s)"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr "%s تتداخل مع %s"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr "الفترة يجب أن تكون مميزة لكل مؤسسة !"
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr "نوع الفترة يجب أن يكون مميزاً لكل مؤسسة !"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr "نشط"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr "السماح بالتداخل"
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "إلغاء"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr "المؤسسة"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "أنشئ بواسطة"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "أنشئ في"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr "الفترة الزمنية"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+#, fuzzy
+msgid "Date Range Generator"
+msgstr "نوع الفترة الزمنية"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr "نوع الفترة الزمنية"
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr "أنواع الفترات الزمنية"
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr "الفترات الزمنية"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr "الفترة الزمنية"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr "نوع الفترة الزمنية"
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr "الفترات الزمنية"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "اسم العرض"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr "المدة الزمنية"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr "تاريخ الانتهاء"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr "إنشاء فترات زمنية"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "المعرف"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "آخر تعديل في"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "آخر تحديث بواسطة"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "آخر تحديث في"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "الاسم"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr "عدد الفترات المطلوبة"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr "بادئة اسم الفترات"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr "الفترات الزمنية"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr "تاريخ البدء"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr "إنشاء"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr "المؤسسة في الفترة الزمنية وفي نوع الفترة يجب أن تكون متطابقة."
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr "المؤسسة في الفترة الزمنية وفي نوع الفترة يجب أن تكون متطابقة."
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "النوع"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "الاسم"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr "الوحدة الزمنية"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+"لا يمكنك تغيير المؤسسة، حيث أن نوع الفترة تم تعيينه للفترة الزمنية (%s)."
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr "أيام"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr "أشهر"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr "أسابيع"
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr "سنوات"
+
+#~ msgid "Date Start"
+#~ msgstr "تاريخ البدء"
diff --git a/odex30_base/date_range/i18n/bg.po b/odex30_base/date_range/i18n/bg.po
new file mode 100644
index 0000000..6262a80
--- /dev/null
+++ b/odex30_base/date_range/i18n/bg.po
@@ -0,0 +1,452 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Bulgarian (https://www.transifex.com/oca/teams/23907/bg/)\n"
+"Language: bg\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr "Активен"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Откажи"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Създадено от"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Създадено на"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Име за показване"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Последно обновено на"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Последно обновено от"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Последно обновено на"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Име"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Вид"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Име"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/bs.po b/odex30_base/date_range/i18n/bs.po
new file mode 100644
index 0000000..152633f
--- /dev/null
+++ b/odex30_base/date_range/i18n/bs.po
@@ -0,0 +1,453 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Bosnian (https://www.transifex.com/oca/teams/23907/bs/)\n"
+"Language: bs\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
+"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Otkaži"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Kreirao"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Kreirano"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Prikaži naziv"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Zadnje mijenjano"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Zadnji ažurirao"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Zadnje ažurirano"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Ime"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Vrsta"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Ime"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/ca.po b/odex30_base/date_range/i18n/ca.po
new file mode 100644
index 0000000..33afe6a
--- /dev/null
+++ b/odex30_base/date_range/i18n/ca.po
@@ -0,0 +1,452 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Catalan (https://www.transifex.com/oca/teams/23907/ca/)\n"
+"Language: ca\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr "%s no és un rang vàlid (%s > %s)"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr "Actiu"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Cancel·la"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Creat per"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Creat el"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Veure el nom"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Darrera modificació el"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Darrera Actualització per"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Darrera Actualització el"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Nom"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Tipus"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Nom"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/ca_ES.po b/odex30_base/date_range/i18n/ca_ES.po
new file mode 100644
index 0000000..50877de
--- /dev/null
+++ b/odex30_base/date_range/i18n/ca_ES.po
@@ -0,0 +1,452 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2016-12-23 02:01+0000\n"
+"PO-Revision-Date: 2016-12-23 02:01+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Catalan (Spain) (https://www.transifex.com/oca/teams/23907/"
+"ca_ES/)\n"
+"Language: ca_ES\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr "%s no és un rang vàlid (%s > %s)"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Cancel·la"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+msgid "Type Name"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/cs.po b/odex30_base/date_range/i18n/cs.po
new file mode 100644
index 0000000..8083b16
--- /dev/null
+++ b/odex30_base/date_range/i18n/cs.po
@@ -0,0 +1,452 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Czech (https://www.transifex.com/oca/teams/23907/cs/)\n"
+"Language: cs\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Zrušit"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Vytvořil(a)"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Vytvořeno"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Zobrazovaný název"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Naposled upraveno"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Naposled upraveno"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Naposled upraveno"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Název"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Druh"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Název"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/da.po b/odex30_base/date_range/i18n/da.po
new file mode 100644
index 0000000..71b4f39
--- /dev/null
+++ b/odex30_base/date_range/i18n/da.po
@@ -0,0 +1,457 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2018-09-06 08:11+0000\n"
+"Last-Translator: Hans Henrik Gabelgaard \n"
+"Language-Team: Danish (https://www.transifex.com/oca/teams/23907/da/)\n"
+"Language: da\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Weblate 3.1.1\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr "%s er ikke et gyldigt interval (%s > %s)"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr "%s overlapper %s"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr "Et dato interval skal være unikt inden for virksomheden!"
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr "En dato intervaltype skal være unikt inden for virksomheden!"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr "Aktiv"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr "Tillad overlap"
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Annuller"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr "Virksomhed"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Oprettet af"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Oprettet den"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr "Dato interval"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+#, fuzzy
+msgid "Date Range Generator"
+msgstr "Intervaltype"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr "Intervaltype"
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr "Intervaltyper"
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr "Dato intervaller"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr "Dato interval"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr "Intervaltype"
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr "Dato intervaller"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Vist navn"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr "Varighed"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr "Slut dato"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr "Generer dato intervaller"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "Id"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Sidst ændret den"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Sidst opdateret af"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Sidst opdateret den"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Navn"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr "Antal intervaller der genereres"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr "Prefix for interval navn"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr "Intervaller"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr "Start dato"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr "Indsend"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Type"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Navn"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr "Tidsenhed"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr "dage"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr "måneder"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr "uger"
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr "år"
+
+#~ msgid "Date Start"
+#~ msgstr "Start dato"
diff --git a/odex30_base/date_range/i18n/de.po b/odex30_base/date_range/i18n/de.po
new file mode 100644
index 0000000..b736f63
--- /dev/null
+++ b/odex30_base/date_range/i18n/de.po
@@ -0,0 +1,473 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: German (https://www.transifex.com/oca/teams/23907/de/)\n"
+"Language: de\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr "%s ist nicht im erlaubten Bereich (%s > %s)"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr "%s überlappt %s"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr "Ein Zeitbereich muss pro Unternehmen eindeutig sein!"
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr "Ein Zeitbereich muss pro Unternehmen eindeutig sein!"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr "Aktiv"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+#, fuzzy
+msgid "Allow Overlap"
+msgstr "Erlaube Überlappungen"
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Abbrechen"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr "Unternehmen"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Erstellt von"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Erstellt am:"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr "Datumsbereich"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+#, fuzzy
+msgid "Date Range Generator"
+msgstr "date.range.generator"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr "Datumsbereichstyp"
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr "Datumsbereichstypen"
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr "Datumsbereiche"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr "Datumsbereich"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr "Datumsbereichstyp"
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr "Zeiträume"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Anzeigename"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr "Dauer"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr "Enddatum"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr "Datumsbereiche generieren"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+"Wenn gesetzt darf der Datumsbereich des gleichen Typs nicht überlappen."
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Zuletzt geändert am"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Zuletzt aktualisiert von"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Zuletzt aktualisiert am"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Name"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr "Anzahl der zu generierenden Bereiche"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr "Bereichs-Präfix"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+#, fuzzy
+msgid "Ranges"
+msgstr "Datumsbereiche"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr "Anfangsdatum"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr "Senden"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+#, fuzzy
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+"Das aktive Feld erlaubt den Zeitbereich zu verbergen ohne ihn zu entfernen."
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+"Das aktive Feld erlaubt den Zeitbereich zu verbergen ohne ihn zu entfernen."
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Typ"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Name"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+#, fuzzy
+msgid "Unit Of Time"
+msgstr "Zeiteinheit"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr "Tage"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr "Monate"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr "Wochen"
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr "Jahre"
+
+#, fuzzy
+#~ msgid "Date Start"
+#~ msgstr "Anfangsdatum"
+
+#~ msgid "date.range"
+#~ msgstr "date.range"
+
+#~ msgid "date.range.type"
+#~ msgstr "date.range.type"
+
+#~ msgid "Genrate Date Ranges"
+#~ msgstr "Datumsbereiche generieren"
diff --git a/odex30_base/date_range/i18n/el_GR.po b/odex30_base/date_range/i18n/el_GR.po
new file mode 100644
index 0000000..b6d6c2e
--- /dev/null
+++ b/odex30_base/date_range/i18n/el_GR.po
@@ -0,0 +1,453 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Greek (Greece) (https://www.transifex.com/oca/teams/23907/"
+"el_GR/)\n"
+"Language: el_GR\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Δημιουργήθηκε από "
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Δημιουργήθηκε στις"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "Κωδικός"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Τελευταία ενημέρωση από"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Τελευταία ενημέρωση στις"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Ονομασία"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Τύπος"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Ονομασία"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/en_AU.po b/odex30_base/date_range/i18n/en_AU.po
new file mode 100644
index 0000000..a4cca90
--- /dev/null
+++ b/odex30_base/date_range/i18n/en_AU.po
@@ -0,0 +1,452 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2016-12-23 02:01+0000\n"
+"PO-Revision-Date: 2016-12-23 02:01+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: English (Australia) (https://www.transifex.com/oca/"
+"teams/23907/en_AU/)\n"
+"Language: en_AU\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Cancel"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+msgid "Type Name"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/en_GB.po b/odex30_base/date_range/i18n/en_GB.po
new file mode 100644
index 0000000..c848a94
--- /dev/null
+++ b/odex30_base/date_range/i18n/en_GB.po
@@ -0,0 +1,453 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: English (United Kingdom) (https://www.transifex.com/oca/"
+"teams/23907/en_GB/)\n"
+"Language: en_GB\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Cancel"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Created by"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Created on"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Display Name"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Last Modified on"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Last Updated by"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Last Updated on"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Name"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Type"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Name"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/es.po b/odex30_base/date_range/i18n/es.po
new file mode 100644
index 0000000..de6714d
--- /dev/null
+++ b/odex30_base/date_range/i18n/es.po
@@ -0,0 +1,471 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2021-03-16 11:46+0000\n"
+"Last-Translator: Ana Suárez \n"
+"Language-Team: Spanish (https://www.transifex.com/oca/teams/23907/es/)\n"
+"Language: es\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Weblate 4.3.2\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr "%s no es un rango válido (%s > %s)"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr "%s solapa con %s"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr "¡El rango de fechas debe ser único por compañía!"
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr "¡El tipo de rango de fechas debe ser único por compañía!"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr "Activo"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr "Permitir solapamiento"
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Cancelar"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr "Compañía"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Creado por"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Creado en"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr "Rango de fechas"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr "Generador de rangos de fecha"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr "Tipo de rango de fechas"
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr "Tipos de rango de fechas"
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr "Rangos de fechas"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr "Rango de fechas"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr "Tipo de rango de fechas"
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr "Rangos de fechas"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Nombre mostrado"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr "Duración"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr "Fecha final"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr "Generar rangos de fechas"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+"Si está establecido, los rangos de fechas del mismo tipo no deben solapar."
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Modificado por última vez el"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Última actualización de"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Última actualización en"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Nombre"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr "Número de rangos a generar"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr "Prefijo del nombre del rango"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr "Rangos"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr "Fecha de inicio"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr "Enviar"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+"La compañía en el generador de rangos de fecha y en el tipo de rango de "
+"fecha debe ser el mismo."
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+"La compañía en el rango de fecha y en el tipo de rango de fecha debe ser el "
+"mismo."
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr "El campo activo permite esconder un rango de fechas sin eliminarlo."
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr "El campo activo permite esconder un rango de fechas sin eliminarlo."
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Tipo"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+msgid "Type Name"
+msgstr "Nombre del tipo"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr "Unidad de tiempo"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+"No puede modificar la compañía porque este tipo d rango de fecha está "
+"asignado a un rango de fecha (%s)."
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr "días"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr "meses"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr "semanas"
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr "años"
+
+#~ msgid "Date Start"
+#~ msgstr "Fecha de inicio"
+
+#~ msgid "date.range"
+#~ msgstr "date.range"
+
+#~ msgid "date.range.type"
+#~ msgstr "date.range.type"
+
+#~ msgid "Genrate Date Ranges"
+#~ msgstr "Generar rangos de fechas"
diff --git a/odex30_base/date_range/i18n/es_AR.po b/odex30_base/date_range/i18n/es_AR.po
new file mode 100644
index 0000000..23d359d
--- /dev/null
+++ b/odex30_base/date_range/i18n/es_AR.po
@@ -0,0 +1,453 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Spanish (Argentina) (https://www.transifex.com/oca/"
+"teams/23907/es_AR/)\n"
+"Language: es_AR\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Cancelar"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Creado por"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Creado en"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Mostrar Nombre"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Última modificación en"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Última actualización realizada por"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Última actualización el"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Nombre"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Tipo"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Nombre"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/es_CL.po b/odex30_base/date_range/i18n/es_CL.po
new file mode 100644
index 0000000..7f7b914
--- /dev/null
+++ b/odex30_base/date_range/i18n/es_CL.po
@@ -0,0 +1,453 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Spanish (Chile) (https://www.transifex.com/oca/teams/23907/"
+"es_CL/)\n"
+"Language: es_CL\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Cancelar"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Creado por"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Creado en"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Nombre mostrado"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID (identificación)"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Última modificación en"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Última actualización de"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Última actualización en"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Nombre"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Tipo"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Nombre"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/es_CO.po b/odex30_base/date_range/i18n/es_CO.po
new file mode 100644
index 0000000..27b2524
--- /dev/null
+++ b/odex30_base/date_range/i18n/es_CO.po
@@ -0,0 +1,453 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Spanish (Colombia) (https://www.transifex.com/oca/teams/23907/"
+"es_CO/)\n"
+"Language: es_CO\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Cancelar"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Creado por"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Creado"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Nombre Público"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Última Modificación el"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Actualizado por"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Actualizado"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Nombre"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Tipo"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Nombre"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/es_CR.po b/odex30_base/date_range/i18n/es_CR.po
new file mode 100644
index 0000000..fdd9528
--- /dev/null
+++ b/odex30_base/date_range/i18n/es_CR.po
@@ -0,0 +1,453 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Spanish (Costa Rica) (https://www.transifex.com/oca/"
+"teams/23907/es_CR/)\n"
+"Language: es_CR\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Cancelar"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Creado por"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Creado en"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Ultima actualización por"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Ultima actualización en"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Nombre"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Tipo"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Nombre"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/es_DO.po b/odex30_base/date_range/i18n/es_DO.po
new file mode 100644
index 0000000..9f862ac
--- /dev/null
+++ b/odex30_base/date_range/i18n/es_DO.po
@@ -0,0 +1,453 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Spanish (Dominican Republic) (https://www.transifex.com/oca/"
+"teams/23907/es_DO/)\n"
+"Language: es_DO\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Cancelar"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Creado por"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Creado en"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Nombre mostrado"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID (identificación)"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Última modificación en"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Última actualización de"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Última actualización en"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Nombre"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Tipo"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Nombre"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/es_EC.po b/odex30_base/date_range/i18n/es_EC.po
new file mode 100644
index 0000000..6a3c0fd
--- /dev/null
+++ b/odex30_base/date_range/i18n/es_EC.po
@@ -0,0 +1,453 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Spanish (Ecuador) (https://www.transifex.com/oca/teams/23907/"
+"es_EC/)\n"
+"Language: es_EC\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Cancelar"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Creado por"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Creado en"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Nombre mostrado"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Última modificación en"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Última actualización de"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Última actualización en"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Nombre"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Tipo"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Nombre"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/es_ES.po b/odex30_base/date_range/i18n/es_ES.po
new file mode 100644
index 0000000..36feb16
--- /dev/null
+++ b/odex30_base/date_range/i18n/es_ES.po
@@ -0,0 +1,453 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Spanish (Spain) (https://www.transifex.com/oca/teams/23907/"
+"es_ES/)\n"
+"Language: es_ES\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Cancelar"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Creado por"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Creado en"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Nombre para mostrar"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Última modificación en"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Última actualización por"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Última actualización en"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Tipo"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Tipo"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/es_MX.po b/odex30_base/date_range/i18n/es_MX.po
new file mode 100644
index 0000000..a9d7238
--- /dev/null
+++ b/odex30_base/date_range/i18n/es_MX.po
@@ -0,0 +1,453 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Spanish (Mexico) (https://www.transifex.com/oca/teams/23907/"
+"es_MX/)\n"
+"Language: es_MX\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Cancelar"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Creado por"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Creado en"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Nombre desplegado"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Ultima modificacion realizada"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Ultima actualización por"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Ultima actualización en"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Nombre"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Tipo"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Nombre"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/es_PE.po b/odex30_base/date_range/i18n/es_PE.po
new file mode 100644
index 0000000..51bbf94
--- /dev/null
+++ b/odex30_base/date_range/i18n/es_PE.po
@@ -0,0 +1,453 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2017
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2017\n"
+"Language-Team: Spanish (Peru) (https://www.transifex.com/oca/teams/23907/"
+"es_PE/)\n"
+"Language: es_PE\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Creado por"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Creado en"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Nombre a Mostrar"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Ultima Modificación en"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Actualizado última vez por"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Ultima Actualización"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Nombre"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Tipo"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Nombre"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/es_PY.po b/odex30_base/date_range/i18n/es_PY.po
new file mode 100644
index 0000000..1838c95
--- /dev/null
+++ b/odex30_base/date_range/i18n/es_PY.po
@@ -0,0 +1,453 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Spanish (Paraguay) (https://www.transifex.com/oca/teams/23907/"
+"es_PY/)\n"
+"Language: es_PY\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Cancelar"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Creado por"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Creado en"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Ultima actualización por"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Ultima actualización en"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Nombre"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Tipo"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Nombre"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/es_VE.po b/odex30_base/date_range/i18n/es_VE.po
new file mode 100644
index 0000000..9930b20
--- /dev/null
+++ b/odex30_base/date_range/i18n/es_VE.po
@@ -0,0 +1,453 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Spanish (Venezuela) (https://www.transifex.com/oca/"
+"teams/23907/es_VE/)\n"
+"Language: es_VE\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Cancelar"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Creado por"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Creado en"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Mostrar nombre"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Modificada por última vez"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Ultima actualización por"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Ultima actualización en"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Nombre"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Tipo"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Nombre"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/et.po b/odex30_base/date_range/i18n/et.po
new file mode 100644
index 0000000..43d86f7
--- /dev/null
+++ b/odex30_base/date_range/i18n/et.po
@@ -0,0 +1,452 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Estonian (https://www.transifex.com/oca/teams/23907/et/)\n"
+"Language: et\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Loobu"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Loonud"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Loodud"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Näidatav nimi"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Viimati muudetud"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Viimati uuendatud"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Viimati uuendatud"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Nimi"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Tüüp"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Nimi"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/eu.po b/odex30_base/date_range/i18n/eu.po
new file mode 100644
index 0000000..cf09be7
--- /dev/null
+++ b/odex30_base/date_range/i18n/eu.po
@@ -0,0 +1,452 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Basque (https://www.transifex.com/oca/teams/23907/eu/)\n"
+"Language: eu\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Ezeztatu"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Nork sortua"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Created on"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Izena erakutsi"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Last Updated by"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Last Updated on"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Izena"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Mota"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Izena"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/fa.po b/odex30_base/date_range/i18n/fa.po
new file mode 100644
index 0000000..cd67356
--- /dev/null
+++ b/odex30_base/date_range/i18n/fa.po
@@ -0,0 +1,452 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Persian (https://www.transifex.com/oca/teams/23907/fa/)\n"
+"Language: fa\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "لغو"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "ایجاد شده توسط"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "ایجاد شده در"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "نام نمایشی"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "شناسه"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "تاریخ آخرین بهروزرسانی"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "آخرین به روز رسانی توسط"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "آخرین به روز رسانی در"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "نام"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "نوع"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "نام"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/fi.po b/odex30_base/date_range/i18n/fi.po
new file mode 100644
index 0000000..734faf0
--- /dev/null
+++ b/odex30_base/date_range/i18n/fi.po
@@ -0,0 +1,452 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Finnish (https://www.transifex.com/oca/teams/23907/fi/)\n"
+"Language: fi\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr "Aktiivinen"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Peruuta"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Luonut"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Luotu"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Nimi"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Viimeksi muokattu"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Viimeksi päivittänyt"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Viimeksi päivitetty"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Nimi"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Tyyppi"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Nimi"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/fr.po b/odex30_base/date_range/i18n/fr.po
new file mode 100644
index 0000000..49db874
--- /dev/null
+++ b/odex30_base/date_range/i18n/fr.po
@@ -0,0 +1,453 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2020-12-13 18:36+0000\n"
+"Last-Translator: Stéphane Bidoul (ACSONE) \n"
+"Language-Team: French (https://www.transifex.com/oca/teams/23907/fr/)\n"
+"Language: fr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=n > 1;\n"
+"X-Generator: Weblate 4.3.2\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr "Actif"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Annuler"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr "Société"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Créé par"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Créé le"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Nom d'affichage"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Dernière modification le"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Mis à jour par"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Mis à jour le"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Nom"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Type"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Nom"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr "Unité de temps"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/fr_CA.po b/odex30_base/date_range/i18n/fr_CA.po
new file mode 100644
index 0000000..003ea6e
--- /dev/null
+++ b/odex30_base/date_range/i18n/fr_CA.po
@@ -0,0 +1,453 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: French (Canada) (https://www.transifex.com/oca/teams/23907/"
+"fr_CA/)\n"
+"Language: fr_CA\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Annuler"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Créé par"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Créé le"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Afficher le nom"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "Identifiant"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Dernière mise à jour par"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Dernière mise à jour le"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Nom"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Type"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Nom"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/fr_CH.po b/odex30_base/date_range/i18n/fr_CH.po
new file mode 100644
index 0000000..6aa1c07
--- /dev/null
+++ b/odex30_base/date_range/i18n/fr_CH.po
@@ -0,0 +1,453 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: French (Switzerland) (https://www.transifex.com/oca/"
+"teams/23907/fr_CH/)\n"
+"Language: fr_CH\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr "Actif"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Annuler"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Créé par"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Créé le"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Nom affiché"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Dernière modification le"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Modifié par"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Modifié le"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Type"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Type"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/fr_FR.po b/odex30_base/date_range/i18n/fr_FR.po
new file mode 100644
index 0000000..c709fd6
--- /dev/null
+++ b/odex30_base/date_range/i18n/fr_FR.po
@@ -0,0 +1,467 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2021-04-11 18:46+0000\n"
+"Last-Translator: Yves Le Doeuff \n"
+"Language-Team: French (France) (https://www.transifex.com/oca/teams/23907/"
+"fr_FR/)\n"
+"Language: fr_FR\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=n > 1;\n"
+"X-Generator: Weblate 4.3.2\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr "%s n'est pas une plage valide (%s > %s)"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr "%s chevauchements %s"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr "Une plage de dates doit être unique par société !"
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr "Un type de plage de dates doit être unique par société !"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr "Actif"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr "Autoriser les chevauchements"
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Annuler"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr "Société"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Créé par"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Créé le"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr "Plage de dates"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr "Générateur de plages de dates"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr "Type de plages de dates"
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr "Types de plages de dates"
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr "Plages de dates"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr "Plage de dates"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr "Type de plage de dates"
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr "Plages de dates"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Nom d'affichage"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr "Durée"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr "Date de fin"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr "Générer les plages de dates"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+"Si elle est définie, les plages de dates de même type ne doivent pas se "
+"chevaucher."
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Dernière modification le"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Mis à jour par"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Mis à jour le"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Nom"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr "Nombre de plages à générer"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr "Préfixe du nom de plage"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr "Plages"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr "Date de début"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr "Soumettre"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+"La société dans le générateur de plage de dates et dans le type de plage de "
+"dates doit être la même."
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+"La société dans la plage de dates et dans le type de plage de dates doit "
+"être la même."
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+"Le champ actif vous permet de masquer le type de plage de dates sans le "
+"supprimer."
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+"Le champ actif vous permet de masquer la plage de dates sans la supprimer."
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Type"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+msgid "Type Name"
+msgstr "Nom"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr "Unité de temps"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+"Vous ne pouvez pas modifier la société, car ce type de plage de dates est "
+"attribué à la plage de dates (%s)."
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr "jours"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr "mois"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr "semaines"
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr "années"
+
+#~ msgid "Date Start"
+#~ msgstr "Date de début"
diff --git a/odex30_base/date_range/i18n/gl.po b/odex30_base/date_range/i18n/gl.po
new file mode 100644
index 0000000..78f2a31
--- /dev/null
+++ b/odex30_base/date_range/i18n/gl.po
@@ -0,0 +1,452 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Galician (https://www.transifex.com/oca/teams/23907/gl/)\n"
+"Language: gl\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Cancelar"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Creado por"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Creado en"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Modificado por última vez o"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "ültima actualización por"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Última actualización en"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Nome"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Tipo"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Nome"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/gl_ES.po b/odex30_base/date_range/i18n/gl_ES.po
new file mode 100644
index 0000000..195efb1
--- /dev/null
+++ b/odex30_base/date_range/i18n/gl_ES.po
@@ -0,0 +1,452 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2016-11-26 03:36+0000\n"
+"PO-Revision-Date: 2016-11-26 03:36+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Galician (Spain) (https://www.transifex.com/oca/teams/23907/"
+"gl_ES/)\n"
+"Language: gl_ES\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+msgid "Type Name"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/he.po b/odex30_base/date_range/i18n/he.po
new file mode 100644
index 0000000..89632c2
--- /dev/null
+++ b/odex30_base/date_range/i18n/he.po
@@ -0,0 +1,452 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Hebrew (https://www.transifex.com/oca/teams/23907/he/)\n"
+"Language: he\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "בטל"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "נוצר על ידי"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "נוצר ב-"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "השם המוצג"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "מזהה"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "תאריך שינוי אחרון"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "עודכן לאחרונה על ידי"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "עודכן לאחרונה על"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "שם"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "סוג"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "שם"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/hi.po b/odex30_base/date_range/i18n/hi.po
new file mode 100644
index 0000000..ea25bbd
--- /dev/null
+++ b/odex30_base/date_range/i18n/hi.po
@@ -0,0 +1,451 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2016-12-23 02:01+0000\n"
+"PO-Revision-Date: 2016-12-23 02:01+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Hindi (https://www.transifex.com/oca/teams/23907/hi/)\n"
+"Language: hi\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "रद्द"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+msgid "Type Name"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/hr.po b/odex30_base/date_range/i18n/hr.po
new file mode 100644
index 0000000..c00e9ee
--- /dev/null
+++ b/odex30_base/date_range/i18n/hr.po
@@ -0,0 +1,471 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Croatian (https://www.transifex.com/oca/teams/23907/hr/)\n"
+"Language: hr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
+"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr "%s nije valjani raspon (%s > %s)"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr "%s preklapa se sa %s"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr "Raspon datuma mora biti jedinstven unutar tvrtke!"
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr "Tip raspona datuma mora biti jedinstven unutar tvrtke!"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr "Aktivan"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+#, fuzzy
+msgid "Allow Overlap"
+msgstr "Dozvoli preklapanje"
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Otkaži"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr "Poduzeće"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Kreirao"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Kreirano"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr "Raspon datuma"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+#, fuzzy
+msgid "Date Range Generator"
+msgstr "date.range.generator"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr "Tip raspona datuma"
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr "Tipovi raspona datuma"
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr "Rasponi datuma"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr "Raspon datuma"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr "Tip raspona datuma"
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr "Rasponi datuma"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Naziv (za prikaz)"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr "Trajanje"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr "Datum završetka"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr "Generiraj raspone datuma"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr "Ako je uključeno rasponi datuma istog tima nesmije se preklapati"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Zadnje modificirano"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Zadnji ažurirao"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Zadnje ažuriranje"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Ime"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr "Broj raspona za generiranje"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr "Prefiks naziva raspona"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+#, fuzzy
+msgid "Ranges"
+msgstr "Rasponi datuma"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr "Početni datum"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr "Izvrši"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+#, fuzzy
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr "Polje aktivan omogućuje sakrivanje raspona bez da ga brišete."
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr "Polje aktivan omogućuje sakrivanje raspona bez da ga brišete."
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Tip"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Ime"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+#, fuzzy
+msgid "Unit Of Time"
+msgstr "Jedinica vremena"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr "dana"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr "mjeseci"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr "tjedana"
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr "godina"
+
+#, fuzzy
+#~ msgid "Date Start"
+#~ msgstr "Datum početka"
+
+#~ msgid "date.range"
+#~ msgstr "date.range"
+
+#~ msgid "date.range.type"
+#~ msgstr "date.range.type"
+
+#~ msgid "Genrate Date Ranges"
+#~ msgstr "Generiraj raspone datuma"
diff --git a/odex30_base/date_range/i18n/hr_HR.po b/odex30_base/date_range/i18n/hr_HR.po
new file mode 100644
index 0000000..de2a456
--- /dev/null
+++ b/odex30_base/date_range/i18n/hr_HR.po
@@ -0,0 +1,454 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Croatian (Croatia) (https://www.transifex.com/oca/teams/23907/"
+"hr_HR/)\n"
+"Language: hr_HR\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
+"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr "Aktivan"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Otkaži"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Kreirao"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Kreirano"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Naziv"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Zadnje modificirano"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Zadnje ažurirao"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Zadnje ažurirano"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Naziv"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Tip"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Naziv"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/hu.po b/odex30_base/date_range/i18n/hu.po
new file mode 100644
index 0000000..4cc8c40
--- /dev/null
+++ b/odex30_base/date_range/i18n/hu.po
@@ -0,0 +1,452 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Hungarian (https://www.transifex.com/oca/teams/23907/hu/)\n"
+"Language: hu\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Mégsem"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Készítette"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Létrehozás dátuma"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Név megjelenítése"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "Azonosító ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Utolsó frissítés dátuma"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Utoljára frissítve, által"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Utoljára frissítve ekkor"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Név"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Típus"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Név"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/id.po b/odex30_base/date_range/i18n/id.po
new file mode 100644
index 0000000..c8eb084
--- /dev/null
+++ b/odex30_base/date_range/i18n/id.po
@@ -0,0 +1,452 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Indonesian (https://www.transifex.com/oca/teams/23907/id/)\n"
+"Language: id\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Batalkan"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Dibuat oleh"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Dibuat pada"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Nama Tampilan"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Terakhir Dimodifikasi pada"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Diperbaharui oleh"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Diperbaharui pada"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Nama"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Jenis"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Nama"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/it.po b/odex30_base/date_range/i18n/it.po
new file mode 100644
index 0000000..8073fc3
--- /dev/null
+++ b/odex30_base/date_range/i18n/it.po
@@ -0,0 +1,465 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2018-12-24 16:58+0000\n"
+"Last-Translator: Sergio Zanchetta \n"
+"Language-Team: Italian (https://www.transifex.com/oca/teams/23907/it/)\n"
+"Language: it\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Weblate 3.3\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr "%s non è un intervallo valido (%s > %s)"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr "%s è sovrapposto a %s"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr "Un intervallo data deve essere univoco per azienda !"
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr "Un tipo di intervallo data deve essere univoco per azienda !"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr "Attivo"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr "Consentire sovrapposizione"
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Annulla"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr "Azienda"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Creato da"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Creato il"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr "Intervallo data"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr "Generatore intervallo data"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr "Tipo di intervallo data"
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr "Tipi di intervallo data"
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr "Intervalli data"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr "Intervallo data"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr "Tipo di intervallo data"
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr "Intervalli data"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Nome visualizzato"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr "Durata"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr "Data finale"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr "Generazione intervalli data"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+"Se impostato, gli intervalli data dello stesso tipo non devono sovrapporsi."
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Ultima modifica il"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Ultimo aggiornamento di"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Ultimo aggiornamento il"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Nome"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr "Numero di intervalli da generare"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr "Prefisso nome intervallo"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr "Intervalli"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr "Data iniziale"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr "Invia"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+"Le aziende nel generatore intervallo data e nel tipo di intervallo data "
+"devono corrispondere."
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+"Le aziende nell'intervallo data e nel tipo di intervallo data devono "
+"corrispondere."
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+"Il campo attivo consente di nascondere il tipo di intervallo data senza "
+"rimuoverlo."
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+"Il campo attivo consente di nascondere l'intervallo data senza rimuoverlo."
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Tipo"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+msgid "Type Name"
+msgstr "Nome tipo"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr "Unità di tempo"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+"Impossibile modificare l'azienda, questo tipo di intervallo data è già "
+"assegnato all'intervallo (%s)."
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr "giorni"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr "mesi"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr "settimane"
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr "anni"
+
+#~ msgid "Date Start"
+#~ msgstr "Data iniziale"
diff --git a/odex30_base/date_range/i18n/ja.po b/odex30_base/date_range/i18n/ja.po
new file mode 100644
index 0000000..1d8a0e4
--- /dev/null
+++ b/odex30_base/date_range/i18n/ja.po
@@ -0,0 +1,452 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Japanese (https://www.transifex.com/oca/teams/23907/ja/)\n"
+"Language: ja\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "取消"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "作成者"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "作成日"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "表示名"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "最終更新日"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "最終更新者"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "最終更新日"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "名称"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "タイプ"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "名称"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/ko.po b/odex30_base/date_range/i18n/ko.po
new file mode 100644
index 0000000..7ee9b2a
--- /dev/null
+++ b/odex30_base/date_range/i18n/ko.po
@@ -0,0 +1,452 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Korean (https://www.transifex.com/oca/teams/23907/ko/)\n"
+"Language: ko\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "취소"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "작성자"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "작성일"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "표시 이름"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "최근 수정"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "최근 갱신한 사람"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "최근 갱신 날짜"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "이름"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "유형"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "이름"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/lo.po b/odex30_base/date_range/i18n/lo.po
new file mode 100644
index 0000000..b91178d
--- /dev/null
+++ b/odex30_base/date_range/i18n/lo.po
@@ -0,0 +1,451 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2016-12-23 02:01+0000\n"
+"PO-Revision-Date: 2016-12-23 02:01+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Lao (https://www.transifex.com/oca/teams/23907/lo/)\n"
+"Language: lo\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "ຍົກເລີອກ"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+msgid "Type Name"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/lt.po b/odex30_base/date_range/i18n/lt.po
new file mode 100644
index 0000000..2677808
--- /dev/null
+++ b/odex30_base/date_range/i18n/lt.po
@@ -0,0 +1,453 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Lithuanian (https://www.transifex.com/oca/teams/23907/lt/)\n"
+"Language: lt\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n"
+"%100<10 || n%100>=20) ? 1 : 2);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Atšaukti"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Sukūrė"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Sukurta"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Vaizduojamas pavadinimas"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Paskutinį kartą keista"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Paskutini kartą atnaujino"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Paskutinį kartą atnaujinta"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Pavadinimas"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Tipas"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Pavadinimas"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/lt_LT.po b/odex30_base/date_range/i18n/lt_LT.po
new file mode 100644
index 0000000..3959e22
--- /dev/null
+++ b/odex30_base/date_range/i18n/lt_LT.po
@@ -0,0 +1,453 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2016-12-23 02:01+0000\n"
+"PO-Revision-Date: 2016-12-23 02:01+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Lithuanian (Lithuania) (https://www.transifex.com/oca/"
+"teams/23907/lt_LT/)\n"
+"Language: lt_LT\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n"
+"%100<10 || n%100>=20) ? 1 : 2);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Atšaukti"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Sukūrė"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Sukurta"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Paskutinį kartą atnaujino"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Paskutinį kartą atnaujinta"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+msgid "Type Name"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/lv.po b/odex30_base/date_range/i18n/lv.po
new file mode 100644
index 0000000..736fab4
--- /dev/null
+++ b/odex30_base/date_range/i18n/lv.po
@@ -0,0 +1,453 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Latvian (https://www.transifex.com/oca/teams/23907/lv/)\n"
+"Language: lv\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : "
+"2);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Atcelt"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Izveidoja"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Izveidots"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Pēdējo reizi atjaunoja"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Pēdējās izmaiņas"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Nosaukums"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Tips"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Nosaukums"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/mk.po b/odex30_base/date_range/i18n/mk.po
new file mode 100644
index 0000000..51b32ff
--- /dev/null
+++ b/odex30_base/date_range/i18n/mk.po
@@ -0,0 +1,452 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Macedonian (https://www.transifex.com/oca/teams/23907/mk/)\n"
+"Language: mk\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Откажи"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Креирано од"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Креирано на"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Прикажи име"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Последна промена на"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Последно ажурирање од"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Последно ажурирање на"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Име"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Тип"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Име"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/mn.po b/odex30_base/date_range/i18n/mn.po
new file mode 100644
index 0000000..0889de4
--- /dev/null
+++ b/odex30_base/date_range/i18n/mn.po
@@ -0,0 +1,452 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Mongolian (https://www.transifex.com/oca/teams/23907/mn/)\n"
+"Language: mn\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Цуцлах"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Үүсгэгч"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Үүсгэсэн огноо"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Дэлгэцийн Нэр"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Сүүлийн засвар хийсэн огноо"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Сүүлийн засвар хийсэн"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Сүүлийн засвар хийсэн огноо"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Нэр"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Төрөл"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Нэр"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/nb.po b/odex30_base/date_range/i18n/nb.po
new file mode 100644
index 0000000..30f20a4
--- /dev/null
+++ b/odex30_base/date_range/i18n/nb.po
@@ -0,0 +1,453 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Norwegian Bokmål (https://www.transifex.com/oca/teams/23907/"
+"nb/)\n"
+"Language: nb\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Avbryt"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Opprettet av"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Opprettet"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Visnings navn"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Sist oppdatert "
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Sist oppdatert av"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Sist oppdatert"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Navn"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Type"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Navn"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/nb_NO.po b/odex30_base/date_range/i18n/nb_NO.po
new file mode 100644
index 0000000..766c85f
--- /dev/null
+++ b/odex30_base/date_range/i18n/nb_NO.po
@@ -0,0 +1,452 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2016-12-23 02:01+0000\n"
+"PO-Revision-Date: 2016-12-23 02:01+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Norwegian Bokmål (Norway) (https://www.transifex.com/oca/"
+"teams/23907/nb_NO/)\n"
+"Language: nb_NO\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Lukk"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Laget av"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Laget den"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Vis navn"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Sist endret den"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Sist oppdatert av"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Sist oppdatert den"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+msgid "Type Name"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/nl.po b/odex30_base/date_range/i18n/nl.po
new file mode 100644
index 0000000..d3b4dbf
--- /dev/null
+++ b/odex30_base/date_range/i18n/nl.po
@@ -0,0 +1,466 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2021-04-18 10:46+0000\n"
+"Last-Translator: Bosd \n"
+"Language-Team: Dutch (https://www.transifex.com/oca/teams/23907/nl/)\n"
+"Language: nl\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Weblate 4.3.2\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr "%s is een ongeldige reeks (%s > %s)"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr "%s overlapt %s"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr "Een datumreeks moet uniek zijn per bedrijf!"
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr "Een datumreekssoort moet uniek zijn per bedrijf!"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr "Actief"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr "Overlappen toestaan"
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Annuleren"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr "Bedrijf"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Aangemaakt door"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Aangemaakt op"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr "Datumreeks"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr "Datumreeks Generator"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr "Datumreekssoort"
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr "Datumreekssoorten"
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr "Datumreeksen"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr "Datumreeks"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr "Datumreekssoort"
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr "Datumreeksen"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Te tonen naam"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr "Duur"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr "Einddatum"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr "Genereer Datumreeksen"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+"Indien ingesteld mogen datum bereiken van hetzelfde type niet overlappen."
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Laatst bijgewerkt op"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Laatste bijgewerkt door"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Laatst bijgewerkt op"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Naam"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr "Aantal te genereren reeksen"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr "Voorvoegsel voor reeksnaam"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr "Reeksen"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr "Startdatum"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr "Verzenden"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+"Het bedrijf in de datumreeksgenerator en in de datumreekssoort moeten "
+"hetzelfde zijn."
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+"Het bedrijf in de datumreeks en in de datumreekssoort moeten hetzelfde zijn."
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+"Het actieve veld geeft u de mogelijkheid om een datum bereik inactief te "
+"maken zonder deze te verwijderen."
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+"Het actief veld geeft u de mogelijkheid om een datum bereik inactief te "
+"maken zonder deze te verwijderen."
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Type"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Naam"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr "Eenheid van tijd"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+"U kunt het bedrijf niet wijzigen, omdat deze range type is ingesteld op "
+"Datum bereik (%s)."
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr "dagen"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr "maanden"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr "weken"
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr "jaren"
+
+#~ msgid "Date Start"
+#~ msgstr "Start Datum"
diff --git a/odex30_base/date_range/i18n/nl_BE.po b/odex30_base/date_range/i18n/nl_BE.po
new file mode 100644
index 0000000..5e4f684
--- /dev/null
+++ b/odex30_base/date_range/i18n/nl_BE.po
@@ -0,0 +1,453 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Dutch (Belgium) (https://www.transifex.com/oca/teams/23907/"
+"nl_BE/)\n"
+"Language: nl_BE\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Annuleren"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Gemaakt door"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Gemaakt op"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Schermnaam"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Laatst Aangepast op"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Laatst bijgewerkt door"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Laatst bijgewerkt op"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Naam:"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Type"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Naam:"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/nl_NL.po b/odex30_base/date_range/i18n/nl_NL.po
new file mode 100644
index 0000000..54d1e51
--- /dev/null
+++ b/odex30_base/date_range/i18n/nl_NL.po
@@ -0,0 +1,476 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2017
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2017\n"
+"Language-Team: Dutch (Netherlands) (https://www.transifex.com/oca/"
+"teams/23907/nl_NL/)\n"
+"Language: nl_NL\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr "%s is geen geldig bereik (%s > %s)"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr "%s overlapt %s"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr "Een datum bereik moet uniek zijn per bedrijf !"
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr "Een datum bereik type moet uniek zijn per bedrijf !"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr "Actief"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+#, fuzzy
+msgid "Allow Overlap"
+msgstr "Sta overlap toe"
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Annuleer"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr "Bedrijf"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Aangemaakt door"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Aangemaakt op"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr "Datumbereik"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+#, fuzzy
+msgid "Date Range Generator"
+msgstr "date.range.generator"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr "Datumbereik type"
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr "Datumbereik types"
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr "Datumbereiken"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr "Datumbereik"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr "Datumbereik type"
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr "Datumbereiken"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "weergavenaam"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr "Duur"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr "Einddatum"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr "Genereer datum bereiken"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+"Indien ingesteld ogen datum bereiken van hetzelfde type niet overlappen."
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Laatst gewijzigd op"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Laatst bijgewerkt door"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Laatst bijgewerkt op"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Naam"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr "Aantal bereiken te genereren"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr "Bereik naam prefix"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+#, fuzzy
+msgid "Ranges"
+msgstr "Datumbereiken"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr "Startdatum"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr "Indienen"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+#, fuzzy
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+"Het actief veld geeft u de mogelijkheid om een datum bereik inactief te "
+"maken zonder deze te verwijderen."
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+"Het actief veld geeft u de mogelijkheid om een datum bereik inactief te "
+"maken zonder deze te verwijderen."
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Type"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Naam"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+#, fuzzy
+msgid "Unit Of Time"
+msgstr "Eenheid van tijd"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr "dagen"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr "maanden"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr "weken"
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr "jaren"
+
+#, fuzzy
+#~ msgid "Date Start"
+#~ msgstr "Startdatum"
+
+#~ msgid "date.range"
+#~ msgstr "date.range"
+
+#~ msgid "date.range.type"
+#~ msgstr "date.range.type"
+
+#~ msgid "Genrate Date Ranges"
+#~ msgstr "Genereer datum bereiken"
diff --git a/odex30_base/date_range/i18n/pl.po b/odex30_base/date_range/i18n/pl.po
new file mode 100644
index 0000000..093347b
--- /dev/null
+++ b/odex30_base/date_range/i18n/pl.po
@@ -0,0 +1,454 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Polish (https://www.transifex.com/oca/teams/23907/pl/)\n"
+"Language: pl\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n"
+"%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n"
+"%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Anuluj"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Utworzone przez"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Data utworzenia"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Wyświetlana nazwa "
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Ostatnio modyfikowano"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Ostatnio modyfikowane przez"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Data ostatniej modyfikacji"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Nazwa"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Typ"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Nazwa"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/pt.po b/odex30_base/date_range/i18n/pt.po
new file mode 100644
index 0000000..ed2dc10
--- /dev/null
+++ b/odex30_base/date_range/i18n/pt.po
@@ -0,0 +1,467 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2019-08-14 12:44+0000\n"
+"Last-Translator: Pedro Castro Silva \n"
+"Language-Team: Portuguese (https://www.transifex.com/oca/teams/23907/pt/)\n"
+"Language: pt\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Weblate 3.7.1\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr "%s não é um período válido (%s > %s)"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr "%s sobrepõe-se a %s"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr "Um período deve ser único em cada empresa !"
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr "Um tipo de período deve ser único em cada empresa !"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr "Ativo"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr "Permitir Sobreposição"
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Cancelar"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr "Empresa"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Criado por"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Criado em"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr "Período"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr "Gerador de Períodos"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr "Tipo de Período"
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr "Tipos de Períodos"
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr "Períodos"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr "Período"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr "Tipo de Período"
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr "Períodos"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Nome a Apresentar"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr "Duração"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr "Data de fim"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr "Gerar Períodos"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr "Se verdadeiro, períodos do mesmo tipo não se podem sobrepôr."
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Modificado a última vez por"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Atualizado pela última vez por"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Atualizado pela última vez em"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Nome"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr "Número de períodos a gerar"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr "Prefixo do período"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr "Períodos"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr "Data de início"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr "Submeter"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+"A Empresa no Gerador de Períodos e no Tipo de Período tem que ser a mesma."
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr "A Empresa no Período e no Tipo de Período tem que ser a mesma."
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr "O campo Ativo permite-lhe esconder o período sem o remover."
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr "O campo Ativo permite-lhe esconder o período sem o remover."
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Tipo"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+msgid "Type Name"
+msgstr "Nome do Tipo"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr "Unidade de Tempo"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+"Não pode alterar a empresa, uma vez que este Tipo de Período está atribuído "
+"ao Período (%s)."
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr "dias"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr "meses"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr "semanas"
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr "anos"
+
+#~ msgid "Date Start"
+#~ msgstr "Data Inicial"
+
+#~ msgid "date.range"
+#~ msgstr "date.range"
+
+#~ msgid "date.range.type"
+#~ msgstr "date.range.type"
+
+#~ msgid "Genrate Date Ranges"
+#~ msgstr "Gerar Períodos"
diff --git a/odex30_base/date_range/i18n/pt_BR.po b/odex30_base/date_range/i18n/pt_BR.po
new file mode 100644
index 0000000..6188641
--- /dev/null
+++ b/odex30_base/date_range/i18n/pt_BR.po
@@ -0,0 +1,461 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2019-11-25 15:58+0000\n"
+"Last-Translator: Luis Felipe Miléo \n"
+"Language-Team: Portuguese (Brazil) (https://www.transifex.com/oca/"
+"teams/23907/pt_BR/)\n"
+"Language: pt_BR\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=n > 1;\n"
+"X-Generator: Weblate 3.8\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr "%s não é válido para o intervalo de datas (%s > %s)"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr "%s sobrepoe %s"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr "O intervalo de datas deve ser único por empresa!"
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr "O intervalo de datas deve ser único por empresa !"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr "Ativo"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr "Permitir sobreposição"
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Cancelar"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr "Empresa"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Criado por"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Criado em"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr "Intervalo de datas"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr "Gerar intervalo de datas"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr "Tipo de intervalo de data"
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr "Tipos de períodos"
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr "Períodos"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr "Data final"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr "Tipo de intervalo de data"
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr "Períodos"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Nome para Mostrar"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr "Duração"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr "Data final"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr "Gerar intervalo de datas"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "Identificação"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr "Se define o período do mesmo tipo, não deve se sobrepor."
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Última atualização em"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Última atualização por"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Última atualização em"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Nome"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr "Número de intervalos a serem gerados"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr "Prefixo do nome do intervalo"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr "Intervalos"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr "Data inicial"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr "Confirmar"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Tipo"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Nome"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+#, fuzzy
+msgid "Unit Of Time"
+msgstr "Unidade de tempo"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
+
+#~ msgid "Date Start"
+#~ msgstr "Data incial"
+
+#~ msgid "date.range.type"
+#~ msgstr "date.range.type"
diff --git a/odex30_base/date_range/i18n/pt_PT.po b/odex30_base/date_range/i18n/pt_PT.po
new file mode 100644
index 0000000..6f78a61
--- /dev/null
+++ b/odex30_base/date_range/i18n/pt_PT.po
@@ -0,0 +1,453 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Portuguese (Portugal) (https://www.transifex.com/oca/"
+"teams/23907/pt_PT/)\n"
+"Language: pt_PT\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr "Ativo"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Cancelar"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Criado por"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Criado em"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Nome a Apresentar"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Última Modificação em"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Atualizado pela última vez por"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Atualizado pela última vez em"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Nome"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Tipo"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Nome"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/ro.po b/odex30_base/date_range/i18n/ro.po
new file mode 100644
index 0000000..3fcce61
--- /dev/null
+++ b/odex30_base/date_range/i18n/ro.po
@@ -0,0 +1,453 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Romanian (https://www.transifex.com/oca/teams/23907/ro/)\n"
+"Language: ro\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?"
+"2:1));\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Anuleaza"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Creat de"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Creat la"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Nume Afişat"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Ultima actualizare în"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Ultima actualizare făcută de"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Ultima actualizare la"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Nume"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Tip"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Nume"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/ru.po b/odex30_base/date_range/i18n/ru.po
new file mode 100644
index 0000000..0a8148a
--- /dev/null
+++ b/odex30_base/date_range/i18n/ru.po
@@ -0,0 +1,454 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Russian (https://www.transifex.com/oca/teams/23907/ru/)\n"
+"Language: ru\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
+"%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n"
+"%100>=11 && n%100<=14)? 2 : 3);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Отменена"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Создано"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Создан"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Последний раз обновлено"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Последний раз обновлено"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Название"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Тип"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Название"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/sk.po b/odex30_base/date_range/i18n/sk.po
new file mode 100644
index 0000000..8a870a9
--- /dev/null
+++ b/odex30_base/date_range/i18n/sk.po
@@ -0,0 +1,452 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Slovak (https://www.transifex.com/oca/teams/23907/sk/)\n"
+"Language: sk\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr "Aktívne"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Zrušiť"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Vytvoril"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Vytvorené"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Zobraziť meno"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Posledná modifikácia"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Naposledy upravoval"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Naposledy upravované"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Meno"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Typ"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Meno"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/sl.po b/odex30_base/date_range/i18n/sl.po
new file mode 100644
index 0000000..5829aa8
--- /dev/null
+++ b/odex30_base/date_range/i18n/sl.po
@@ -0,0 +1,453 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Slovenian (https://www.transifex.com/oca/teams/23907/sl/)\n"
+"Language: sl\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n"
+"%100==4 ? 2 : 3);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr "Aktivno"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Preklic"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr "Družba"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Ustvaril"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Ustvarjeno"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Prikazani naziv"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Zadnjič spremenjeno"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Zadnji posodobil"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Zadnjič posodobljeno"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Naziv"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Tip"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Naziv"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/sr.po b/odex30_base/date_range/i18n/sr.po
new file mode 100644
index 0000000..67372aa
--- /dev/null
+++ b/odex30_base/date_range/i18n/sr.po
@@ -0,0 +1,453 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Serbian (https://www.transifex.com/oca/teams/23907/sr/)\n"
+"Language: sr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
+"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Otkaži"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Kreiran"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Ime"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Tip"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Ime"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/sr@latin.po b/odex30_base/date_range/i18n/sr@latin.po
new file mode 100644
index 0000000..8ed6687
--- /dev/null
+++ b/odex30_base/date_range/i18n/sr@latin.po
@@ -0,0 +1,454 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Serbian (Latin) (https://www.transifex.com/oca/teams/23907/"
+"sr@latin/)\n"
+"Language: sr@latin\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
+"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Otkaži"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Kreirao"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Kreiran"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Ime za prikaz"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Zadnja izmjena"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Zadnja izmjena"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Zadnja izmjena"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Ime:"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Tip"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Ime:"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/sv.po b/odex30_base/date_range/i18n/sv.po
new file mode 100644
index 0000000..e071dfa
--- /dev/null
+++ b/odex30_base/date_range/i18n/sv.po
@@ -0,0 +1,452 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Swedish (https://www.transifex.com/oca/teams/23907/sv/)\n"
+"Language: sv\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Avbryt"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Skapad av"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Skapad den"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Visa namn"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Senast redigerad"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Senast uppdaterad av"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Senast uppdaterad"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Namn"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Typ"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Namn"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/th.po b/odex30_base/date_range/i18n/th.po
new file mode 100644
index 0000000..f06d610
--- /dev/null
+++ b/odex30_base/date_range/i18n/th.po
@@ -0,0 +1,452 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Thai (https://www.transifex.com/oca/teams/23907/th/)\n"
+"Language: th\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "ยกเลิก"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "สร้างโดย"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "สร้างเมื่อ"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "ชื่อที่ใช้แสดง"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "รหัส"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "แก้ไขครั้งสุดท้ายเมื่อ"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "อัพเดทครั้งสุดท้ายโดย"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "อัพเดทครั้งสุดท้ายเมื่อ"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "ชื่อ"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "ชนิด"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "ชื่อ"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/tr.po b/odex30_base/date_range/i18n/tr.po
new file mode 100644
index 0000000..6df298d
--- /dev/null
+++ b/odex30_base/date_range/i18n/tr.po
@@ -0,0 +1,452 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Turkish (https://www.transifex.com/oca/teams/23907/tr/)\n"
+"Language: tr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr "Aktif"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Vazgeç"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Oluşturan"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Oluşturuldu"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Görünen İsim"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Son değişiklik"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Son güncelleyen"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Son güncellenme"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Adı"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Tür"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Adı"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/tr_TR.po b/odex30_base/date_range/i18n/tr_TR.po
new file mode 100644
index 0000000..bec5953
--- /dev/null
+++ b/odex30_base/date_range/i18n/tr_TR.po
@@ -0,0 +1,453 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2017
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2017\n"
+"Language-Team: Turkish (Turkey) (https://www.transifex.com/oca/teams/23907/"
+"tr_TR/)\n"
+"Language: tr_TR\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr "Etkin"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Oluşturan"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Oluşturulma tarihi"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Görünen ad"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "Kimlik"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "En son güncelleme tarihi"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "En son güncelleyen "
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "En son güncelleme tarihi"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Ad"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Tip"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Ad"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/uk.po b/odex30_base/date_range/i18n/uk.po
new file mode 100644
index 0000000..a3738bd
--- /dev/null
+++ b/odex30_base/date_range/i18n/uk.po
@@ -0,0 +1,453 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Ukrainian (https://www.transifex.com/oca/teams/23907/uk/)\n"
+"Language: uk\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
+"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Скасувати"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Створив"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Створено"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Назва для відображення"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Остання модифікація"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Востаннє відредаговано"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Дата останньої зміни"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Name"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Тип"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Name"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/vi.po b/odex30_base/date_range/i18n/vi.po
new file mode 100644
index 0000000..3d19bba
--- /dev/null
+++ b/odex30_base/date_range/i18n/vi.po
@@ -0,0 +1,452 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Vietnamese (https://www.transifex.com/oca/teams/23907/vi/)\n"
+"Language: vi\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Hủy bỏ"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Được tạo bởi"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Tạo trên"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "Tên hiển thị"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "Sửa lần cuối vào"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Last Updated by"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Cập nhật lần cuối vào"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Tên"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "Loại"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Tên"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/vi_VN.po b/odex30_base/date_range/i18n/vi_VN.po
new file mode 100644
index 0000000..736f504
--- /dev/null
+++ b/odex30_base/date_range/i18n/vi_VN.po
@@ -0,0 +1,453 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-02-18 02:29+0000\n"
+"PO-Revision-Date: 2017-02-18 02:29+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Vietnamese (Viet Nam) (https://www.transifex.com/oca/"
+"teams/23907/vi_VN/)\n"
+"Language: vi_VN\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "Hủy"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "Tạo bởi"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "Tạo vào"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "Cập nhật lần cuối bởi"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "Cập nhật lần cuối vào"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "Tên"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "Tên"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/i18n/zh_CN.po b/odex30_base/date_range/i18n/zh_CN.po
new file mode 100644
index 0000000..994b9a4
--- /dev/null
+++ b/odex30_base/date_range/i18n/zh_CN.po
@@ -0,0 +1,459 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2020-03-21 15:14+0000\n"
+"Last-Translator: Dong \n"
+"Language-Team: Chinese (China) (https://www.transifex.com/oca/teams/23907/"
+"zh_CN/)\n"
+"Language: zh_CN\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"X-Generator: Weblate 3.10\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr "%s 不是有效的日期范围 (%s > %s)"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr "%s 重叠 %s"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr "每个公司的日期范围必须是唯一的!"
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr "每个公司的日期范围类型必须是唯一的!"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr "有效"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr "允许重叠"
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "取消"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr "公司"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "创建者"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "创建时间"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr "日期范围"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr "日期范围生成器"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr "日期范围类型"
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr "日期范围类型"
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr "日期范围"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr "日期范围"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr "日期范围类型"
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr "日期范围"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "显示名称"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr "持续时间"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr "结束日期"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr "生成日期范围"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr "如果设置相同类型的日期范围不得重叠。"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "最后修改时间"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "最后更新者"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "最后更新时间"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "名称"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr "要生成的范围数"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr "范围名称前缀"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr "范围"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr "开始日期"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr "提交"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr "日期范围生成器和日期范围类型中的公司必须相同。"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr "日期范围和日期范围类型中的公司必须相同。"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr "活动字段允许您隐藏日期范围类型而不删除它。"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr "活动字段允许您隐藏日期范围而不删除它。"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "类型"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+msgid "Type Name"
+msgstr "类型名称"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr "单位时间"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr "您无法更改公司,因为此日期范围类型已分配给日期范围(%s)。"
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr "天"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr "月"
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr "周"
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr "年"
+
+#~ msgid "Date Start"
+#~ msgstr "开始日期"
+
+#~ msgid "Genrate Date Ranges"
+#~ msgstr "生成日期范围"
diff --git a/odex30_base/date_range/i18n/zh_TW.po b/odex30_base/date_range/i18n/zh_TW.po
new file mode 100644
index 0000000..4888f74
--- /dev/null
+++ b/odex30_base/date_range/i18n/zh_TW.po
@@ -0,0 +1,453 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * date_range
+#
+# Translators:
+# OCA Transbot , 2016
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2017-08-01 02:44+0000\n"
+"PO-Revision-Date: 2017-08-01 02:44+0000\n"
+"Last-Translator: OCA Transbot , 2016\n"
+"Language-Team: Chinese (Taiwan) (https://www.transifex.com/oca/teams/23907/"
+"zh_TW/)\n"
+"Language: zh_TW\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s is not a valid range (%s > %s)"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "%s overlaps %s"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid " "
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid ""
+",\n"
+" or generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_date_range_uniq
+msgid "A date range must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.constraint,message:date_range.constraint_date_range_type_date_range_type_uniq
+msgid "A date range type must be unique per company !"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__active
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__active
+msgid "Active"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__allow_overlap
+msgid "Allow Overlap"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.server,name:date_range.ir_cron_autocreate_ir_actions_server
+#: model:ir.cron,cron_name:date_range.ir_cron_autocreate
+#: model:ir.cron,name:date_range.ir_cron_autocreate
+msgid "Auto-generate date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Auto-generation settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_count
+msgid "Autogeneration Count"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_date_start
+msgid "Autogeneration Start Date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__autogeneration_unit
+msgid "Autogeneration Unit"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Cancel"
+msgstr "取消"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__company_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__company_id
+msgid "Company"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Configuration"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Create"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_uid
+msgid "Created by"
+msgstr "建立者"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__create_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__create_date
+msgid "Created on"
+msgstr "建立於"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range
+msgid "Date Range"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_generator
+msgid "Date Range Generator"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_type
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Date Range Type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_type_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_type_action
+msgid "Date Range Types"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_action
+msgid "Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_ranges_exist
+msgid "Date Ranges Exist"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_tree
+msgid "Date range"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_tree
+msgid "Date range type"
+msgstr ""
+
+#. module: date_range
+#: model:ir.ui.menu,name:date_range.menu_date_range
+msgid "Date ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Defaults for generating date ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__display_name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__display_name
+msgid "Display Name"
+msgstr "顯示名稱"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__duration_count
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__duration_count
+msgid "Duration"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_end
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_end
+msgid "End date"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,help:date_range.field_date_range_type__name_expr
+msgid ""
+"Evaluated expression. E.g. \"'FY%s' % date_start.strftime('%Y%m%d')\"\n"
+"You can use the Date types 'date_end' and 'date_start', as well as the "
+"'index' variable."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__date_range_search_id
+msgid "Filter by period (technical field)"
+msgstr ""
+
+#. module: date_range
+#: model:ir.actions.act_window,name:date_range.date_range_generator_action
+#: model:ir.ui.menu,name:date_range.menu_date_range_generator_action
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Generate Date Ranges"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "Generation"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin__id
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__id
+msgid "ID"
+msgstr "ID"
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__allow_overlap
+msgid "If sets date range of same type must not overlap."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Invalid name expression: %s"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_search_mixin____last_update
+#: model:ir.model.fields,field_description:date_range.field_date_range_type____last_update
+msgid "Last Modified on"
+msgstr "最後修改:"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_uid
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_uid
+msgid "Last Updated by"
+msgstr "最後更新:"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__write_date
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__write_date
+msgid "Last Updated on"
+msgstr "最後更新於"
+
+#. module: date_range
+#: model:ir.model,name:date_range.model_date_range_search_mixin
+msgid "Mixin class to add a Many2one style period search field"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__name
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name
+msgid "Name"
+msgstr "名稱"
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "No ranges to generate with these settings"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__count
+msgid "Number of ranges to generate"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__autogeneration_date_start
+msgid "Only applies when there are no date ranges of this type yet"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Parameters"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_search_mixin.py:0
+#, python-format
+msgid "Period"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please enter an end date, or the number of ranges to generate."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid "Please set a prefix or an expression to generate the range names."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__range_name_preview
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__range_name_preview
+msgid "Range Name Preview"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_expr
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_expr
+msgid "Range name expression"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__name_prefix
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__name_prefix
+msgid "Range name prefix"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__date_range_ids
+msgid "Ranges"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__date_start
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__date_start
+msgid "Start date"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Submit"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/wizard/date_range_generator.py:0
+#, python-format
+msgid ""
+"The Company in the Date Range Generator and in Date Range Type must be the "
+"same."
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range.py:0
+#, python-format
+msgid "The Company in the Date Range and in Date Range Type must be the same."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range_type__active
+msgid ""
+"The active field allows you to hide the date range type without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,help:date_range.field_date_range__active
+msgid "The active field allows you to hide the date range without removing it."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_id
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__type_id
+msgid "Type"
+msgstr "類型"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range__type_name
+#, fuzzy
+msgid "Type Name"
+msgstr "名稱"
+
+#. module: date_range
+#: model:ir.model.fields,field_description:date_range.field_date_range_generator__unit_of_time
+#: model:ir.model.fields,field_description:date_range.field_date_range_type__unit_of_time
+msgid "Unit Of Time"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "Until"
+msgstr ""
+
+#. module: date_range
+#: code:addons/date_range/models/date_range_type.py:0
+#, python-format
+msgid ""
+"You cannot change the company, as this Date Range Type is assigned to Date "
+"Range (%s)."
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__3
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__3
+msgid "days"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+msgid "entries."
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "in advance"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__1
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__1
+msgid "months"
+msgstr ""
+
+#. module: date_range
+#: model_terms:ir.ui.view,arch_db:date_range.date_range_generator_view_form
+#: model_terms:ir.ui.view,arch_db:date_range.view_date_range_type_form_view
+msgid "or enter a complex expression below"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__2
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__2
+msgid "weeks"
+msgstr ""
+
+#. module: date_range
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_generator__unit_of_time__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__autogeneration_unit__0
+#: model:ir.model.fields.selection,name:date_range.selection__date_range_type__unit_of_time__0
+msgid "years"
+msgstr ""
diff --git a/odex30_base/date_range/models/__init__.py b/odex30_base/date_range/models/__init__.py
new file mode 100644
index 0000000..f932e79
--- /dev/null
+++ b/odex30_base/date_range/models/__init__.py
@@ -0,0 +1,5 @@
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from . import date_range_type
+from . import date_range
+from . import date_range_search_mixin
diff --git a/odex30_base/date_range/models/date_range.py b/odex30_base/date_range/models/date_range.py
new file mode 100644
index 0000000..a3d935e
--- /dev/null
+++ b/odex30_base/date_range/models/date_range.py
@@ -0,0 +1,113 @@
+# Copyright 2016 ACSONE SA/NV ()
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from odoo import _, api, fields, models
+from odoo.exceptions import ValidationError
+
+
+class DateRange(models.Model):
+ _name = "date.range"
+ _description = "Date Range"
+ _order = "type_name,date_start"
+
+ @api.model
+ def _default_company(self):
+ return self.env.company
+
+ name = fields.Char(required=True, translate=True)
+ date_start = fields.Date(string="Start date", required=True)
+ date_end = fields.Date(string="End date", required=True)
+ type_id = fields.Many2one(
+ comodel_name="date.range.type",
+ string="Type",
+ index=1,
+ required=True,
+ ondelete="restrict",
+ domain="['|', ('company_id', '=', company_id), " "('company_id', '=', False)]",
+ store=True,
+ compute="_compute_type_id",
+ readonly=False,
+ )
+ type_name = fields.Char(related="type_id.name", store=True, string="Type Name")
+ company_id = fields.Many2one(
+ comodel_name="res.company", string="Company", index=1, default=_default_company
+ )
+ active = fields.Boolean(
+ help="The active field allows you to hide the date range without "
+ "removing it.",
+ default=True,
+ )
+
+ _sql_constraints = [
+ (
+ "date_range_uniq",
+ "unique (name,type_id, company_id)",
+ "A date range must be unique per company !",
+ )
+ ]
+
+ @api.depends("company_id", "type_id.company_id")
+ def _compute_type_id(self):
+ """Enforce check of company consistency when changing company, here
+ or in the type.
+ """
+ self._check_company_id_type_id()
+
+ @api.constrains("company_id", "type_id")
+ def _check_company_id_type_id(self):
+ for rec in self.sudo():
+ if (
+ rec.company_id
+ and rec.type_id.company_id
+ and rec.company_id != rec.type_id.company_id
+ ):
+ raise ValidationError(
+ _(
+ "The Company in the Date Range and in "
+ "Date Range Type must be the same."
+ )
+ )
+
+ @api.constrains("type_id", "date_start", "date_end", "company_id")
+ def _validate_range(self):
+ for this in self:
+ if this.date_start > this.date_end:
+ raise ValidationError(
+ _("%s is not a valid range (%s > %s)")
+ % (this.name, this.date_start, this.date_end)
+ )
+ if this.type_id.allow_overlap:
+ continue
+ # here we use a plain SQL query to benefit of the daterange
+ # function available in PostgresSQL
+ # (http://www.postgresql.org/docs/current/static/rangetypes.html)
+ SQL = """
+ SELECT
+ id
+ FROM
+ date_range dt
+ WHERE
+ DATERANGE(dt.date_start, dt.date_end, '[]') &&
+ DATERANGE(%s::date, %s::date, '[]')
+ AND dt.id != %s
+ AND dt.active
+ AND dt.company_id = %s
+ AND dt.type_id=%s;"""
+ self.env.cr.execute(
+ SQL,
+ (
+ this.date_start,
+ this.date_end,
+ this.id,
+ this.company_id.id or None,
+ this.type_id.id,
+ ),
+ )
+ res = self.env.cr.fetchall()
+ if res:
+ dt = self.browse(res[0][0])
+ raise ValidationError(_("%s overlaps %s") % (this.name, dt.name))
+
+ def get_domain(self, field_name):
+ self.ensure_one()
+ return [(field_name, ">=", self.date_start), (field_name, "<=", self.date_end)]
diff --git a/odex30_base/date_range/models/date_range_search_mixin.py b/odex30_base/date_range/models/date_range_search_mixin.py
new file mode 100644
index 0000000..f98c90c
--- /dev/null
+++ b/odex30_base/date_range/models/date_range_search_mixin.py
@@ -0,0 +1,106 @@
+# Copyright 2021 Opener B.V.
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+from lxml import etree
+
+from odoo import _, api, fields, models
+from odoo.osv.expression import FALSE_DOMAIN, NEGATIVE_TERM_OPERATORS, TRUE_DOMAIN
+
+
+class DateRangeSearchMixin(models.AbstractModel):
+ _name = "date.range.search.mixin"
+ _description = "Mixin class to add a Many2one style period search field"
+ _date_range_search_field = "date"
+
+ date_range_search_id = fields.Many2one(
+ comodel_name="date.range",
+ string="Filter by period (technical field)",
+ compute="_compute_date_range_search_id",
+ search="_search_date_range_search_id",
+ )
+
+ def _compute_date_range_search_id(self):
+ """Assign a dummy value for this search field"""
+ for record in self:
+ record.date_range_search_id = False
+
+ @api.model
+ def _search_date_range_search_id(self, operator, value):
+ """Map the selected date ranges to the model's date field"""
+ # Deal with some bogus values
+ if not value:
+ if operator in NEGATIVE_TERM_OPERATORS:
+ return TRUE_DOMAIN
+ return FALSE_DOMAIN
+ if value is True:
+ if operator in NEGATIVE_TERM_OPERATORS:
+ return FALSE_DOMAIN
+ return TRUE_DOMAIN
+ # Assume from here on that the value is a string,
+ # a single id or a list of ids
+ ranges = self.env["date.range"]
+ if isinstance(value, str):
+ ranges = self.env["date.range"].search([("name", operator, value)])
+ else:
+ if isinstance(value, int):
+ value = [value]
+ sub_op = "not in" if operator in NEGATIVE_TERM_OPERATORS else "in"
+ ranges = self.env["date.range"].search([("id", sub_op, value)])
+ if not ranges:
+ return FALSE_DOMAIN
+ domain = (len(ranges) - 1) * ["|"] + sum(
+ (
+ [
+ "&",
+ (self._date_range_search_field, ">=", date_range.date_start),
+ (self._date_range_search_field, "<=", date_range.date_end),
+ ]
+ for date_range in ranges
+ ),
+ [],
+ )
+ return domain
+
+ @api.model
+ def fields_view_get(
+ self, view_id=None, view_type="form", toolbar=False, submenu=False
+ ):
+ """Inject the dummy Many2one field in the search view"""
+ result = super().fields_view_get(
+ view_id=view_id, view_type=view_type, toolbar=toolbar, submenu=submenu
+ )
+ if view_type != "search":
+ return result
+ root = etree.fromstring(result["arch"])
+ if root.xpath("//field[@name='date_range_search_id']"):
+ # Field was inserted explicitely
+ return result
+ separator = etree.Element("separator")
+ field = etree.Element(
+ "field",
+ attrib={
+ "name": "date_range_search_id",
+ "string": _("Period"),
+ },
+ )
+ groups = root.xpath("/search/group")
+ if groups:
+ groups[0].addprevious(separator)
+ groups[0].addprevious(field)
+ else:
+ search = root.xpath("/search")
+ search[0].append(separator)
+ search[0].append(field)
+ result["arch"] = etree.tostring(root, encoding="unicode")
+ return result
+
+ @api.model
+ def load_views(self, views, options=None):
+ """Adapt the label of the dummy search field
+
+ Ensure the technical name does not show up in the Custom Filter
+ fields list (while still showing up in the Export widget)
+ """
+ result = super().load_views(views, options=options)
+ if "date_range_search_id" in result["fields"]:
+ result["fields"]["date_range_search_id"]["string"] = _("Period")
+ return result
diff --git a/odex30_base/date_range/models/date_range_type.py b/odex30_base/date_range/models/date_range_type.py
new file mode 100644
index 0000000..b0789ff
--- /dev/null
+++ b/odex30_base/date_range/models/date_range_type.py
@@ -0,0 +1,149 @@
+# Copyright 2016 ACSONE SA/NV ()
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+import logging
+
+from dateutil.relativedelta import relativedelta
+from dateutil.rrule import DAILY, MONTHLY, WEEKLY, YEARLY
+
+from odoo import _, api, fields, models
+from odoo.exceptions import ValidationError
+
+
+class DateRangeType(models.Model):
+ _name = "date.range.type"
+ _description = "Date Range Type"
+
+ @api.model
+ def _default_company(self):
+ return self.env.company
+
+ name = fields.Char(required=True, translate=True)
+ allow_overlap = fields.Boolean(
+ help="If sets date range of same type must not overlap.", default=False
+ )
+ active = fields.Boolean(
+ help="The active field allows you to hide the date range type "
+ "without removing it.",
+ default=True,
+ )
+ company_id = fields.Many2one(
+ comodel_name="res.company", string="Company", index=1, default=_default_company
+ )
+ date_range_ids = fields.One2many("date.range", "type_id", string="Ranges")
+ date_ranges_exist = fields.Boolean(compute="_compute_date_ranges_exist")
+
+ # Defaults for generating date ranges
+ name_expr = fields.Text(
+ "Range name expression",
+ help=(
+ "Evaluated expression. E.g. "
+ "\"'FY%s' % date_start.strftime('%Y%m%d')\"\nYou can "
+ "use the Date types 'date_end' and 'date_start', as well as "
+ "the 'index' variable."
+ ),
+ )
+ range_name_preview = fields.Char(compute="_compute_range_name_preview", store=True)
+ name_prefix = fields.Char("Range name prefix")
+ duration_count = fields.Integer("Duration")
+ unit_of_time = fields.Selection(
+ [
+ (str(YEARLY), "years"),
+ (str(MONTHLY), "months"),
+ (str(WEEKLY), "weeks"),
+ (str(DAILY), "days"),
+ ]
+ )
+ autogeneration_date_start = fields.Date(
+ string="Autogeneration Start Date",
+ help="Only applies when there are no date ranges of this type yet",
+ )
+ autogeneration_count = fields.Integer()
+ autogeneration_unit = fields.Selection(
+ [
+ (str(YEARLY), "years"),
+ (str(MONTHLY), "months"),
+ (str(WEEKLY), "weeks"),
+ (str(DAILY), "days"),
+ ]
+ )
+
+ _sql_constraints = [
+ (
+ "date_range_type_uniq",
+ "unique (name,company_id)",
+ "A date range type must be unique per company !",
+ )
+ ]
+
+ @api.constrains("company_id")
+ def _check_company_id(self):
+ if not self.env.context.get("bypass_company_validation", False):
+ for rec in self.sudo():
+ if not rec.company_id:
+ continue
+ if bool(
+ rec.date_range_ids.filtered(
+ lambda r: r.company_id and r.company_id != rec.company_id
+ )
+ ):
+ raise ValidationError(
+ _(
+ "You cannot change the company, as this "
+ "Date Range Type is assigned to Date Range "
+ "(%s)."
+ )
+ % (rec.date_range_ids.name_get()[0][1])
+ )
+
+ @api.depends("name_expr", "name_prefix")
+ def _compute_range_name_preview(self):
+ year_start = fields.Datetime.now().replace(day=1, month=1)
+ next_year = year_start + relativedelta(years=1)
+ for dr_type in self:
+ if dr_type.name_expr or dr_type.name_prefix:
+ names = self.env["date.range.generator"]._generate_names(
+ [year_start, next_year], dr_type.name_expr, dr_type.name_prefix
+ )
+ dr_type.range_name_preview = names[0]
+ else:
+ dr_type.range_name_preview = False
+
+ @api.depends("date_range_ids")
+ def _compute_date_ranges_exist(self):
+ for dr_type in self:
+ dr_type.date_ranges_exist = bool(dr_type.date_range_ids)
+
+ @api.onchange("name_expr")
+ def onchange_name_expr(self):
+ """Wipe the prefix if an expression is entered.
+
+ The reverse is not implemented because we don't want to wipe the
+ users' painstakingly crafted expressions by accident.
+ """
+ if self.name_expr and self.name_prefix:
+ self.name_prefix = False
+
+ @api.model
+ def autogenerate_ranges(self):
+ """Generate ranges for types with autogeneration settings"""
+ logger = logging.getLogger(__name__)
+ for dr_type in self.search(
+ [
+ ("autogeneration_count", "!=", False),
+ ("autogeneration_unit", "!=", False),
+ ("duration_count", "!=", False),
+ ("unit_of_time", "!=", False),
+ ]
+ ):
+ try:
+ wizard = self.env["date.range.generator"].new({"type_id": dr_type.id})
+ if not wizard.date_end:
+ # Nothing to generate
+ continue
+ with self.env.cr.savepoint():
+ wizard.action_apply(batch=True)
+ except Exception as e:
+ logger.warning(
+ "Error autogenerating ranges for date range type "
+ "%s: %s" % (dr_type.name, e)
+ )
diff --git a/odex30_base/date_range/readme/CONFIGURE.rst b/odex30_base/date_range/readme/CONFIGURE.rst
new file mode 100644
index 0000000..ee059d3
--- /dev/null
+++ b/odex30_base/date_range/readme/CONFIGURE.rst
@@ -0,0 +1,24 @@
+For regular usage, see `Usage` below. This section is to clarify optional
+functionality to developers.
+
+To configure a model to use the Many2one style search field, make the model
+inherit from `date.range.search.mixin`:
+
+.. code-block::
+
+ class AccountMove(models.Model):
+ _name = "account.move"
+ _inherit = ["account.move", "date.range.search.mixin"]
+
+This will make a `Period` field show up in the search view:
+
+ .. figure:: https://raw.githubusercontent.com/OCA/server-tools/12.0/date_range/static/description/date_range_many2one_search_field.png
+ :scale: 80 %
+ :alt: Date range Many2one search field
+
+By default, the mixin works on the `date` field. If you want the mixin to work
+on a field with a different name, you can set a property on your model:
+
+.. code-block::
+
+ _date_range_search_field = "invoice_date"
diff --git a/odex30_base/date_range/readme/CONTRIBUTORS.rst b/odex30_base/date_range/readme/CONTRIBUTORS.rst
new file mode 100644
index 0000000..6f06e53
--- /dev/null
+++ b/odex30_base/date_range/readme/CONTRIBUTORS.rst
@@ -0,0 +1,5 @@
+* Laurent Mignon
+* Alexis de Lattre
+* Miquel Raïch
+* Andrea Stirpe
+* Stefan Rijnhart
diff --git a/odex30_base/date_range/readme/DESCRIPTION.rst b/odex30_base/date_range/readme/DESCRIPTION.rst
new file mode 100644
index 0000000..83c4029
--- /dev/null
+++ b/odex30_base/date_range/readme/DESCRIPTION.rst
@@ -0,0 +1,5 @@
+This module lets you define global date ranges that can be used to filter
+your values in tree views.
+
+It also provides a mixin model for developers that extends the model's search
+view so that date ranges can be search as any relational field.
diff --git a/odex30_base/date_range/readme/INSTALL.rst b/odex30_base/date_range/readme/INSTALL.rst
new file mode 100644
index 0000000..f4bf76d
--- /dev/null
+++ b/odex30_base/date_range/readme/INSTALL.rst
@@ -0,0 +1 @@
+The addon use the daterange method from postgres. This method is supported as of postgresql 9.2
diff --git a/odex30_base/date_range/readme/USAGE.rst b/odex30_base/date_range/readme/USAGE.rst
new file mode 100644
index 0000000..556dc01
--- /dev/null
+++ b/odex30_base/date_range/readme/USAGE.rst
@@ -0,0 +1,54 @@
+To configure this module, you need to:
+
+* Go to Settings > Technical > Date ranges > Date Range Types where
+ you can create types of date ranges.
+
+ .. figure:: https://raw.githubusercontent.com/OCA/server-tools/14.0/date_range/static/description/date_range_type_create.png
+ :scale: 80 %
+ :alt: Create a type of date range
+
+* Go to Settings > Technical > Date ranges > Date Ranges where
+ you can create date ranges.
+
+ .. figure:: https://raw.githubusercontent.com/OCA/server-tools/14.0/date_range/static/description/date_range_create.png
+ :scale: 80 %
+ :alt: Date range creation
+
+ It's also possible to launch a wizard from the 'Generate Date Ranges' menu.
+
+ .. figure:: https://raw.githubusercontent.com/OCA/server-tools/14.0/date_range/static/description/date_range_wizard.png
+ :scale: 80 %
+ :alt: Date range wizard
+
+ The wizard is useful to generate recurring periods. Set an end date or enter the number of ranges to create.
+
+ .. figure:: https://raw.githubusercontent.com/OCA/server-tools/14.0/date_range/static/description/date_range_wizard_result.png
+ :scale: 80 %
+ :alt: Date range wizard result
+
+* Your date ranges are now available in the search filter for any date or datetime fields
+
+ Date range types are proposed as a filter operator
+
+ .. figure:: https://raw.githubusercontent.com/OCA/server-tools/14.0/date_range/static/description/date_range_type_as_filter.png
+ :scale: 80 %
+ :alt: Date range type available as filter operator
+
+ Once a type is selected, date ranges of this type are porposed as a filter value
+
+ .. figure:: https://raw.githubusercontent.com/OCA/server-tools/14.0/date_range/static/description/date_range_as_filter.png
+ :scale: 80 %
+ :alt: Date range as filter value
+
+ And the dates specified into the date range are used to filter your result.
+
+ .. figure:: https://raw.githubusercontent.com/OCA/server-tools/14.0/date_range/static/description/date_range_as_filter_result.png
+ :scale: 80 %
+ :alt: Date range as filter result
+
+* You can configure date range types with default values for the generation wizard on the `Generation` tab.
+ In the same tab you can also configure date range types for auto-generation. New ranges for types configured for this are generated by a scheduled task that runs daily.
+
+ .. figure:: https://raw.githubusercontent.com/OCA/server-tools/14.0/date_range/static/description/date_range_type_autogeneration.png
+ :scale: 80 %
+ :alt: Configure a date range for auto-generaton
diff --git a/odex30_base/date_range/security/date_range_security.xml b/odex30_base/date_range/security/date_range_security.xml
new file mode 100644
index 0000000..0b98402
--- /dev/null
+++ b/odex30_base/date_range/security/date_range_security.xml
@@ -0,0 +1,17 @@
+
+
+
+ Date Range Type multi-company
+
+
+ ['|',('company_id', 'in', company_ids),('company_id','=',False)]
+
+
+
+ Date Range multi-company
+
+
+ ['|',('company_id', 'in', company_ids),('company_id','=',False)]
+
+
+
diff --git a/odex30_base/date_range/security/ir.model.access.csv b/odex30_base/date_range/security/ir.model.access.csv
new file mode 100644
index 0000000..5f8c1ca
--- /dev/null
+++ b/odex30_base/date_range/security/ir.model.access.csv
@@ -0,0 +1,6 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+access_date_range_date_range,date_range.date_range,model_date_range,base.group_user,1,0,0,0
+access_date_range_date_range_type,date_range.date_range_type,model_date_range_type,base.group_user,1,0,0,0
+access_date_range_date_range_config,date_range.date_range.config,model_date_range,base.group_system,1,1,1,1
+access_date_range_date_range_type_config,date_range.date_range_type.config,model_date_range_type,base.group_system,1,1,1,1
+access_date_range_generator,access_date_range_generator,model_date_range_generator,base.group_system,1,1,1,1
diff --git a/odex30_base/date_range/static/description/date_range_as_filter.png b/odex30_base/date_range/static/description/date_range_as_filter.png
new file mode 100644
index 0000000..4f61f48
Binary files /dev/null and b/odex30_base/date_range/static/description/date_range_as_filter.png differ
diff --git a/odex30_base/date_range/static/description/date_range_as_filter_result.png b/odex30_base/date_range/static/description/date_range_as_filter_result.png
new file mode 100644
index 0000000..5ba45b7
Binary files /dev/null and b/odex30_base/date_range/static/description/date_range_as_filter_result.png differ
diff --git a/odex30_base/date_range/static/description/date_range_create.png b/odex30_base/date_range/static/description/date_range_create.png
new file mode 100644
index 0000000..f61b3b5
Binary files /dev/null and b/odex30_base/date_range/static/description/date_range_create.png differ
diff --git a/odex30_base/date_range/static/description/date_range_many2one_search_field.png b/odex30_base/date_range/static/description/date_range_many2one_search_field.png
new file mode 100644
index 0000000..32dced0
Binary files /dev/null and b/odex30_base/date_range/static/description/date_range_many2one_search_field.png differ
diff --git a/odex30_base/date_range/static/description/date_range_type_as_filter.png b/odex30_base/date_range/static/description/date_range_type_as_filter.png
new file mode 100644
index 0000000..35148ff
Binary files /dev/null and b/odex30_base/date_range/static/description/date_range_type_as_filter.png differ
diff --git a/odex30_base/date_range/static/description/date_range_type_autogeneration.png b/odex30_base/date_range/static/description/date_range_type_autogeneration.png
new file mode 100644
index 0000000..af1edb6
Binary files /dev/null and b/odex30_base/date_range/static/description/date_range_type_autogeneration.png differ
diff --git a/odex30_base/date_range/static/description/date_range_type_create.png b/odex30_base/date_range/static/description/date_range_type_create.png
new file mode 100644
index 0000000..41e2d92
Binary files /dev/null and b/odex30_base/date_range/static/description/date_range_type_create.png differ
diff --git a/odex30_base/date_range/static/description/date_range_wizard.png b/odex30_base/date_range/static/description/date_range_wizard.png
new file mode 100644
index 0000000..60b20c1
Binary files /dev/null and b/odex30_base/date_range/static/description/date_range_wizard.png differ
diff --git a/odex30_base/date_range/static/description/date_range_wizard_result.png b/odex30_base/date_range/static/description/date_range_wizard_result.png
new file mode 100644
index 0000000..0b0286a
Binary files /dev/null and b/odex30_base/date_range/static/description/date_range_wizard_result.png differ
diff --git a/odex30_base/date_range/static/description/icon.png b/odex30_base/date_range/static/description/icon.png
new file mode 100644
index 0000000..3a0328b
Binary files /dev/null and b/odex30_base/date_range/static/description/icon.png differ
diff --git a/odex30_base/date_range/static/description/icon.svg b/odex30_base/date_range/static/description/icon.svg
new file mode 100644
index 0000000..c237a11
--- /dev/null
+++ b/odex30_base/date_range/static/description/icon.svg
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+ image/svg+xml
+
+
+
+
+
+
+
+
+
+
+
diff --git a/odex30_base/date_range/static/description/index.html b/odex30_base/date_range/static/description/index.html
new file mode 100644
index 0000000..8af6e07
--- /dev/null
+++ b/odex30_base/date_range/static/description/index.html
@@ -0,0 +1,504 @@
+
+
+
+
+
+
+Date Range
+
+
+
+
+
Date Range
+
+
+
+
This module lets you define global date ranges that can be used to filter
+your values in tree views.
+
It also provides a mixin model for developers that extends the model’s search
+view so that date ranges can be search as any relational field.
+
Table of contents
+
+
+
+
The addon use the daterange method from postgres. This method is supported as of postgresql 9.2
+
+
+
+
For regular usage, see Usage below. This section is to clarify optional
+functionality to developers.
+
To configure a model to use the Many2one style search field, make the model
+inherit from date.range.search.mixin :
+
+class AccountMove(models.Model):
+ _name = "account.move"
+ _inherit = ["account.move", "date.range.search.mixin"]
+
+
This will make a Period field show up in the search view:
+
+
+
+
By default, the mixin works on the date field. If you want the mixin to work
+on a field with a different name, you can set a property on your model:
+
+_date_range_search_field = "invoice_date"
+
+
+
+
+
To configure this module, you need to:
+
+Go to Settings > Technical > Date ranges > Date Range Types where
+you can create types of date ranges.
+
+
+Go to Settings > Technical > Date ranges > Date Ranges where
+you can create date ranges.
+
+It’s also possible to launch a wizard from the ‘Generate Date Ranges’ menu.
+
+The wizard is useful to generate recurring periods. Set an end date or enter the number of ranges to create.
+
+
+Your date ranges are now available in the search filter for any date or datetime fields
+Date range types are proposed as a filter operator
+
+Once a type is selected, date ranges of this type are porposed as a filter value
+
+And the dates specified into the date range are used to filter your result.
+
+
+You can configure date range types with default values for the generation wizard on the Generation tab.
+In the same tab you can also configure date range types for auto-generation. New ranges for types configured for this are generated by a scheduled task that runs daily.
+
+
+
+
+
+
+
Bugs are tracked on GitHub Issues .
+In case of trouble, please check there if your issue has already been reported.
+If you spotted it first, help us smashing it by providing a detailed and welcomed
+feedback .
+
Do not contact contributors directly about support or help with technical issues.
+
+
+
+
+
+
+
+
This module is maintained by the OCA.
+
+
OCA, or the Odoo Community Association, is a nonprofit organization whose
+mission is to support the collaborative development of Odoo features and
+promote its widespread use.
+
Current maintainer :
+
+
This module is part of the OCA/server-ux project on GitHub.
+
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute .
+
+
+
+
+
diff --git a/odex30_base/date_range/static/src/js/date_range.js b/odex30_base/date_range/static/src/js/date_range.js
new file mode 100644
index 0000000..663576e
--- /dev/null
+++ b/odex30_base/date_range/static/src/js/date_range.js
@@ -0,0 +1,87 @@
+/* Copyright 2016 ACSONE SA/NV ()
+ * Copyright 2021 Studio73 - Pablo Fuentes (https://www.studio73.es)
+ * License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). */
+
+odoo.define("date_range.CustomFilterItem", function (require) {
+ "use strict";
+
+ const {_lt} = require("web.core");
+ const session = require("web.session");
+ const {FIELD_OPERATORS, FIELD_TYPES} = require("web.searchUtils");
+ const CustomFilterItem = require("web.CustomFilterItem");
+
+ CustomFilterItem.patch(
+ "date_range.CustomFilterItem",
+ (T) =>
+ class extends T {
+ constructor() {
+ super(...arguments);
+ this._computeDateRangeOperators();
+ }
+
+ async _computeDateRangeOperators() {
+ this.OPERATORS = Object.assign({}, FIELD_OPERATORS);
+ this.OPERATORS.date = [...FIELD_OPERATORS.date];
+ this.OPERATORS.datetime = [...FIELD_OPERATORS.datetime];
+ this.date_ranges = {};
+ const result = await this.rpc({
+ model: "date.range",
+ method: "search_read",
+ fields: ["name", "type_id", "date_start", "date_end"],
+ context: session.user_context,
+ });
+ result.forEach((range) => {
+ const range_type = range.type_id[0];
+ if (this.date_ranges[range_type] === undefined) {
+ const r = {
+ symbol: "between",
+ description: `${_lt("in")} ${range.type_id[1]}`,
+ date_range: true,
+ date_range_type: range_type,
+ };
+ this.OPERATORS.date.push(r);
+ this.OPERATORS.datetime.push(r);
+ this.date_ranges[range_type] = [];
+ }
+ this.date_ranges[range_type].push(range);
+ });
+ }
+
+ _setDefaultValue(condition) {
+ const type = this.fields[condition.field].type;
+ const operator = this.OPERATORS[FIELD_TYPES[type]][
+ condition.operator
+ ];
+ if (operator.date_range) {
+ const default_range = this.date_ranges[
+ operator.date_range_type
+ ][0];
+ const d_start = moment(`${default_range.date_start} 00:00:00`);
+ const d_end = moment(`${default_range.date_end} 23:59:59`);
+ condition.value = [d_start, d_end];
+ } else {
+ super._setDefaultValue(...arguments);
+ }
+ }
+
+ _onValueInput(condition, ev) {
+ const type = this.fields[condition.field].type;
+ const operator = this.OPERATORS[FIELD_TYPES[type]][
+ condition.operator
+ ];
+ if (operator.date_range) {
+ const eid = parseInt(ev.target.value);
+ const ranges = this.date_ranges[operator.date_range_type];
+ const range = ranges.find((x) => x.id == eid);
+ const d_start = moment(`${range.date_start} 00:00:00`);
+ const d_end = moment(`${range.date_end} 23:59:59`);
+ condition.value = [d_start, d_end];
+ } else {
+ super._onValueInput(...arguments);
+ }
+ }
+ }
+ );
+
+ return CustomFilterItem;
+});
diff --git a/odex30_base/date_range/static/src/xml/date_range.xml b/odex30_base/date_range/static/src/xml/date_range.xml
new file mode 100644
index 0000000..4b18f62
--- /dev/null
+++ b/odex30_base/date_range/static/src/xml/date_range.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+ $0
+
+
+
diff --git a/odex30_base/date_range/tests/__init__.py b/odex30_base/date_range/tests/__init__.py
new file mode 100644
index 0000000..71b7e85
--- /dev/null
+++ b/odex30_base/date_range/tests/__init__.py
@@ -0,0 +1,6 @@
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from . import test_date_range_type
+from . import test_date_range
+from . import test_date_range_generator
+from . import test_date_range_search_mixin
diff --git a/odex30_base/date_range/tests/models.py b/odex30_base/date_range/tests/models.py
new file mode 100644
index 0000000..e5e2a3a
--- /dev/null
+++ b/odex30_base/date_range/tests/models.py
@@ -0,0 +1,10 @@
+from odoo import fields, models
+
+
+class TestDateRangeSearchMixin(models.Model):
+ _name = "test.date.range.search.mixin"
+ _inherit = ["date.range.search.mixin"]
+ _date_range_search_field = "test_date"
+
+ name = fields.Char()
+ test_date = fields.Date()
diff --git a/odex30_base/date_range/tests/test_date_range.py b/odex30_base/date_range/tests/test_date_range.py
new file mode 100644
index 0000000..567d268
--- /dev/null
+++ b/odex30_base/date_range/tests/test_date_range.py
@@ -0,0 +1,140 @@
+# Copyright 2016 ACSONE SA/NV ()
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
+
+import datetime
+
+from odoo.exceptions import ValidationError
+from odoo.tests.common import TransactionCase
+
+
+class DateRangeTest(TransactionCase):
+ def setUp(self):
+ super(DateRangeTest, self).setUp()
+ self.date_range = self.env["date.range"]
+ self.type = self.env["date.range.type"].create(
+ {"name": "Fiscal year", "company_id": False, "allow_overlap": False}
+ )
+
+ self.company = self.env["res.company"].create({"name": "Test company"})
+ self.company_2 = self.env["res.company"].create(
+ {"name": "Test company 2", "parent_id": self.company.id}
+ )
+ self.typeB = self.env["date.range.type"].create(
+ {
+ "name": "Fiscal year B",
+ "company_id": self.company.id,
+ "allow_overlap": False,
+ }
+ )
+
+ def test_default_company(self):
+ dr = self.date_range.create(
+ {
+ "name": "FS2016",
+ "date_start": "2015-01-01",
+ "date_end": "2016-12-31",
+ "type_id": self.type.id,
+ }
+ )
+ self.assertTrue(dr.company_id)
+ # you can specify company_id to False
+ dr = self.date_range.create(
+ {
+ "name": "FS2016_NO_COMPANY",
+ "date_start": "2015-01-01",
+ "date_end": "2016-12-31",
+ "type_id": self.type.id,
+ "company_id": False,
+ }
+ )
+ self.assertFalse(dr.company_id)
+
+ def test_empty_company(self):
+ dr = self.date_range.create(
+ {
+ "name": "FS2016",
+ "date_start": "2015-01-01",
+ "date_end": "2016-12-31",
+ "type_id": self.type.id,
+ "company_id": None,
+ }
+ )
+ self.assertEqual(dr.name, "FS2016")
+
+ def test_invalid(self):
+ with self.assertRaises(ValidationError) as cm:
+ self.date_range.create(
+ {
+ "name": "FS2016",
+ "date_end": "2015-01-01",
+ "date_start": "2016-12-31",
+ "type_id": self.type.id,
+ }
+ )
+ message = str(cm.exception.args[0])
+ self.assertEqual(
+ message, "FS2016 is not a valid range (2016-12-31 > 2015-01-01)"
+ )
+
+ def test_overlap(self):
+ self.date_range.create(
+ {
+ "name": "FS2015",
+ "date_start": "2015-01-01",
+ "date_end": "2015-12-31",
+ "type_id": self.type.id,
+ }
+ )
+ with self.assertRaises(ValidationError) as cm, self.env.cr.savepoint():
+ self.date_range.create(
+ {
+ "name": "FS2016",
+ "date_start": "2015-01-01",
+ "date_end": "2016-12-31",
+ "type_id": self.type.id,
+ }
+ )
+ message = str(cm.exception.args[0])
+ self.assertEqual(message, "FS2016 overlaps FS2015")
+ # check it's possible to overlap if it's allowed by the date range type
+ self.type.allow_overlap = True
+ dr = self.date_range.create(
+ {
+ "name": "FS2016",
+ "date_start": "2015-01-01",
+ "date_end": "2016-12-31",
+ "type_id": self.type.id,
+ }
+ )
+ self.assertEqual(dr.name, "FS2016")
+
+ def test_domain(self):
+ dr = self.date_range.create(
+ {
+ "name": "FS2015",
+ "date_start": "2015-01-01",
+ "date_end": "2015-12-31",
+ "type_id": self.type.id,
+ }
+ )
+ domain = dr.get_domain("my_field")
+ # By default the domain include limits
+ self.assertEqual(
+ domain,
+ [
+ ("my_field", ">=", datetime.date(2015, 1, 1)),
+ ("my_field", "<=", datetime.date(2015, 12, 31)),
+ ],
+ )
+
+ def test_date_range_multicompany_1(self):
+ with self.assertRaises(ValidationError):
+ self.date_range.create(
+ {
+ "name": "FS2016",
+ "date_start": "2015-01-01",
+ "date_end": "2016-12-31",
+ "type_id": self.typeB.id,
+ "company_id": self.company_2.id,
+ }
+ )
diff --git a/odex30_base/date_range/tests/test_date_range_generator.py b/odex30_base/date_range/tests/test_date_range_generator.py
new file mode 100644
index 0000000..9dbe31c
--- /dev/null
+++ b/odex30_base/date_range/tests/test_date_range_generator.py
@@ -0,0 +1,100 @@
+# Copyright 2016 ACSONE SA/NV ()
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)nses/agpl).
+
+import datetime
+
+from dateutil.rrule import MONTHLY
+
+from odoo.exceptions import ValidationError
+from odoo.tests.common import Form, TransactionCase
+
+
+class DateRangeGeneratorTest(TransactionCase):
+ def setUp(self):
+ super(DateRangeGeneratorTest, self).setUp()
+ self.generator = self.env["date.range.generator"]
+ self.type = self.env["date.range.type"].create(
+ {"name": "Fiscal year", "company_id": False, "allow_overlap": False}
+ )
+
+ self.company = self.env["res.company"].create({"name": "Test company"})
+ self.company_2 = self.env["res.company"].create(
+ {"name": "Test company 2", "parent_id": self.company.id}
+ )
+ self.typeB = self.env["date.range.type"].create(
+ {
+ "name": "Fiscal year B",
+ "company_id": self.company.id,
+ "allow_overlap": False,
+ }
+ )
+
+ def test_generate(self):
+ generator = self.generator.create(
+ {
+ "date_start": "1943-01-01",
+ "name_prefix": "1943-",
+ "type_id": self.type.id,
+ "duration_count": 3,
+ "unit_of_time": str(MONTHLY),
+ "count": 4,
+ }
+ )
+ generator.action_apply()
+ ranges = self.env["date.range"].search([("type_id", "=", self.type.id)])
+ self.assertEqual(len(ranges), 4)
+ range4 = ranges[3]
+ self.assertEqual(range4.date_start, datetime.date(1943, 10, 1))
+ self.assertEqual(range4.date_end, datetime.date(1943, 12, 31))
+ self.assertEqual(range4.type_id, self.type)
+
+ def test_generator_multicompany_1(self):
+ with self.assertRaises(ValidationError):
+ self.generator.create(
+ {
+ "date_start": "1943-01-01",
+ "name_prefix": "1943-",
+ "type_id": self.typeB.id,
+ "duration_count": 3,
+ "unit_of_time": str(MONTHLY),
+ "count": 4,
+ "company_id": self.company_2.id,
+ }
+ )
+
+ def test_generator_form(self):
+ """Test validation and onchange functionality"""
+ form = Form(self.env["date.range.generator"])
+ form.type_id = self.type
+ form.unit_of_time = str(MONTHLY)
+ form.duration_count = 10
+ form.date_end = "2021-01-01"
+ # Setting count clears date_end
+ form.count = 10
+ self.assertFalse(form.date_end)
+ # Setting date_end clears count
+ form.date_end = "2021-01-01"
+ self.assertFalse(form.count)
+ form.count = 10
+ form.name_prefix = "PREFIX"
+ # Cannot generate ranges with an invalid name_expr
+ with self.assertRaisesRegex(ValidationError, "Invalid name expression"):
+ form.name_expr = "'not valid"
+ # Setting name_expr clears name_prefix
+ form.name_expr = "'PREFIX%s' % index"
+ self.assertFalse(form.name_prefix)
+ self.assertEqual(form.range_name_preview, "PREFIX01")
+ wizard = form.save()
+
+ # Cannot generate ranges without count and without date_end
+ wizard.date_end = False
+ wizard.count = False
+ with self.assertRaisesRegex(ValidationError, "end date.*number of ranges"):
+ wizard.action_apply()
+
+ wizard.count = 10
+ # Cannot generate ranges without a prefix and without an expression
+ wizard.name_expr = False
+ wizard.name_prefix = False
+ with self.assertRaisesRegex(ValidationError, "prefix.*expression"):
+ wizard.action_apply()
diff --git a/odex30_base/date_range/tests/test_date_range_search_mixin.py b/odex30_base/date_range/tests/test_date_range_search_mixin.py
new file mode 100644
index 0000000..6953ecf
--- /dev/null
+++ b/odex30_base/date_range/tests/test_date_range_search_mixin.py
@@ -0,0 +1,155 @@
+# Copyright 2016 ACSONE SA/NV ()
+# Copyright 2021 Opener B.V.
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+from dateutil.rrule import MONTHLY
+from odoo_test_helper import FakeModelLoader
+
+from odoo.tests import SavepointCase
+
+
+class TestDateRangeearchMixin(SavepointCase):
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass()
+ # Load a test model using odoo_test_helper
+ cls.loader = FakeModelLoader(cls.env, cls.__module__)
+ cls.loader.backup_registry()
+ from .models import TestDateRangeSearchMixin
+
+ cls.loader.update_registry((TestDateRangeSearchMixin,))
+
+ cls.env.user.lang = "en_US"
+ rtype = cls.env["date.range.type"].create(
+ {"name": __name__, "company_id": False, "allow_overlap": False}
+ )
+ cls.env["date.range.generator"].create(
+ {
+ "date_start": "1943-01-01",
+ "name_prefix": "1943-",
+ "type_id": rtype.id,
+ "duration_count": 3,
+ "unit_of_time": str(MONTHLY),
+ "count": 4,
+ }
+ ).action_apply()
+ cls.ranges = cls.env["date.range"].search([("type_id", "=", rtype.id)])
+ cls.model = cls.env[TestDateRangeSearchMixin._name]
+
+ @classmethod
+ def tearDownClass(cls):
+ cls.loader.restore_registry()
+ super().tearDownClass()
+
+ def test_01_search_view(self):
+ """The search field is injected in the model's search view"""
+ self.assertIn(
+ ' ',
+ self.model.fields_view_get(view_type="search")["arch"],
+ )
+ self.assertNotIn(
+ ' ',
+ self.model.fields_view_get(view_type="form")["arch"],
+ )
+ # Having a view with a group element in it
+ view = self.env["ir.ui.view"].create(
+ {
+ "name": __name__,
+ "model": self.model._name,
+ "arch": """
+
+
+
+
+
+
+ """,
+ }
+ )
+ self.assertIn(
+ ' ',
+ self.model.fields_view_get(view_type="search")["arch"],
+ )
+ # Having a view in which the field is added explicitely
+ view.arch = """
+
+
+
+
+
+
+
+ """
+ self.assertNotIn(
+ ' ',
+ self.model.fields_view_get(view_type="search")["arch"],
+ )
+
+ def test_02_search_result(self):
+ """Using the search field leads to expected results"""
+ record = self.model.create({"test_date": "1943-04-05"})
+ self.assertFalse(record.date_range_search_id)
+ self.assertIn(
+ record,
+ self.model.search([("date_range_search_id", "=", self.ranges[1].id)]),
+ )
+ self.assertNotIn(
+ record,
+ self.model.search([("date_range_search_id", "!=", self.ranges[1].id)]),
+ )
+ self.assertIn(
+ record,
+ self.model.search([("date_range_search_id", "!=", self.ranges[0].id)]),
+ )
+ self.assertNotIn(
+ record,
+ self.model.search([("date_range_search_id", "=", self.ranges[0].id)]),
+ )
+ self.assertIn(
+ record, self.model.search([("date_range_search_id", "in", self.ranges.ids)])
+ )
+ self.assertNotIn(
+ record,
+ self.model.search([("date_range_search_id", "not in", self.ranges.ids)]),
+ )
+ self.assertIn(
+ record,
+ self.model.search([("date_range_search_id", "not in", self.ranges[3].ids)]),
+ )
+ self.assertNotIn(
+ record,
+ self.model.search([("date_range_search_id", "in", self.ranges[3].ids)]),
+ )
+ self.assertIn(
+ record, self.model.search([("date_range_search_id", "ilike", "1943")])
+ )
+ self.assertNotIn(
+ record, self.model.search([("date_range_search_id", "not ilike", "1943")])
+ )
+ self.assertIn(
+ record, self.model.search([("date_range_search_id", "not ilike", "2021")])
+ )
+ self.assertNotIn(
+ record, self.model.search([("date_range_search_id", "ilike", "2021")])
+ )
+ self.assertIn(record, self.model.search([("date_range_search_id", "=", True)]))
+ self.assertNotIn(
+ record, self.model.search([("date_range_search_id", "=", False)])
+ )
+ self.assertIn(
+ record, self.model.search([("date_range_search_id", "!=", False)])
+ )
+ self.assertNotIn(
+ record, self.model.search([("date_range_search_id", "!=", True)])
+ )
+
+ def test_03_read(self):
+ """Read returns a falsy value"""
+ record = self.model.create({"test_date": "1943-04-05"})
+ self.assertFalse(record.date_range_search_id)
+
+ def test_04_load_views(self):
+ """Technical field label is replaced in `load_views`"""
+ field = self.model.load_views([(None, "form")])["fields"][
+ "date_range_search_id"
+ ]
+ self.assertNotIn("technical", field["string"])
diff --git a/odex30_base/date_range/tests/test_date_range_type.py b/odex30_base/date_range/tests/test_date_range_type.py
new file mode 100644
index 0000000..20fdec5
--- /dev/null
+++ b/odex30_base/date_range/tests/test_date_range_type.py
@@ -0,0 +1,161 @@
+# Copyright 2016 ACSONE SA/NV ()
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
+
+from dateutil.relativedelta import relativedelta
+from dateutil.rrule import MONTHLY, YEARLY
+from psycopg2 import IntegrityError
+
+from odoo import fields
+from odoo.exceptions import ValidationError
+from odoo.tests.common import TransactionCase
+from odoo.tools import mute_logger
+
+
+class DateRangeTypeTest(TransactionCase):
+ def setUp(self):
+ super(DateRangeTypeTest, self).setUp()
+ self.type = self.env["date.range.type"]
+ self.company = self.env["res.company"].create({"name": "Test company"})
+ self.company_2 = self.env["res.company"].create(
+ {"name": "Test company 2", "parent_id": self.company.id}
+ )
+
+ def test_default_company(self):
+ drt = self.type.create({"name": "Fiscal year", "allow_overlap": False})
+ self.assertTrue(drt.company_id)
+ # you can specify company_id to False
+ drt = self.type.create(
+ {"name": "Fiscal year", "company_id": False, "allow_overlap": False}
+ )
+ self.assertFalse(drt.company_id)
+
+ def test_unlink(self):
+ date_range = self.env["date.range"]
+ drt = self.env["date.range.type"].create(
+ {"name": "Fiscal year", "allow_overlap": False}
+ )
+ date_range.create(
+ {
+ "name": "FS2016",
+ "date_start": "2015-01-01",
+ "date_end": "2016-12-31",
+ "type_id": drt.id,
+ }
+ )
+ with self.assertRaises(IntegrityError), mute_logger("odoo.sql_db"):
+ drt.unlink()
+
+ def test_type_multicompany(self):
+ drt = self.type.create(
+ {"name": "Fiscal year", "company_id": False, "allow_overlap": False}
+ )
+ dr = self.env["date.range"].create(
+ {
+ "name": "FS2016",
+ "date_start": "2015-01-01",
+ "date_end": "2016-12-31",
+ "type_id": drt.id,
+ "company_id": self.company.id,
+ }
+ )
+ drt.company_id = self.company.id
+ with self.assertRaises(ValidationError):
+ dr.company_id = self.company_2
+
+ def test_autogeneration(self):
+ """Ranges are autogenerated for types configured for that"""
+ today = fields.Date.context_today(self.env.user)
+ year_start = today.replace(day=1, month=1)
+ dr_type = self.env["date.range.type"].create(
+ {
+ "name": __name__,
+ "name_expr": "'>%s<' % date_start.strftime('%d%m%Y')",
+ "unit_of_time": str(MONTHLY),
+ "duration_count": 1,
+ "autogeneration_count": 1,
+ "autogeneration_unit": str(YEARLY),
+ }
+ )
+ self.assertEqual(
+ dr_type.range_name_preview, ">%s<" % year_start.strftime("%d%m%Y")
+ )
+
+ self.env["date.range.type"].autogenerate_ranges()
+ ranges = self.env["date.range"].search(
+ [("type_id", "=", dr_type.id)], order="date_start asc"
+ )
+ # For new types, ranges are autogenerated from the start of the year
+ year_start = today.replace(day=1, month=1)
+ self.assertEqual(ranges[0].date_start, year_start)
+ # Ranges are autogenerated upto the range in which the computed end
+ # date falls, c.q. the first of the month a year from now.
+ next_year_month_start = today.replace(day=1) + relativedelta(years=1)
+ self.assertEqual(ranges[-1].date_start, next_year_month_start)
+ self.assertEqual(
+ ranges[-1].name, ">%s<" % next_year_month_start.strftime("%d%m%Y")
+ )
+
+ # No new ranges get generated anymore this month
+ self.env["date.range.type"].autogenerate_ranges()
+ self.assertEqual(
+ len(ranges),
+ len(
+ self.env["date.range"].search(
+ [("type_id", "=", dr_type.id)], order="date_start asc"
+ )
+ ),
+ )
+
+ def test_autogeneration_with_start_date(self):
+ today = fields.Date.context_today(self.env.user)
+ start_date = today.replace(year=2019, day=6, month=1)
+ dr_type = self.env["date.range.type"].create(
+ {
+ "name": __name__,
+ "name_expr": "'>%s<' % date_start.strftime('%d%m%Y')",
+ "unit_of_time": str(MONTHLY),
+ "duration_count": 1,
+ "autogeneration_date_start": start_date,
+ "autogeneration_count": 1,
+ "autogeneration_unit": str(YEARLY),
+ }
+ )
+ self.assertFalse(dr_type.date_ranges_exist)
+ self.env["date.range.type"].autogenerate_ranges()
+ self.assertTrue(dr_type.date_ranges_exist)
+ ranges = self.env["date.range"].search(
+ [("type_id", "=", dr_type.id)], order="date_start asc"
+ )
+ self.assertEqual(ranges[0].date_start, start_date)
+ # No new ranges get generated anymore this month
+ self.env["date.range.type"].autogenerate_ranges()
+ self.assertEqual(
+ len(ranges),
+ len(
+ self.env["date.range"].search(
+ [("type_id", "=", dr_type.id)], order="date_start asc"
+ )
+ ),
+ )
+
+ def test_autogeneration_invalid_config(self):
+ """The cron method does not raise when an invalid config exists"""
+ today = fields.Date.context_today(self.env.user)
+ start_date = today.replace(year=2019, day=6, month=1)
+ dr_type = self.env["date.range.type"].create(
+ {
+ "name": __name__,
+ "name_expr": "index",
+ "unit_of_time": str(MONTHLY),
+ "duration_count": 1,
+ "autogeneration_date_start": start_date,
+ "autogeneration_count": 1,
+ "autogeneration_unit": str(YEARLY),
+ }
+ )
+ # Inject invalid value
+ self.env.cr.execute("UPDATE date_range_type SET name_expr = 'invalid'")
+ dr_type.refresh()
+ with mute_logger("odoo.addons.date_range.models.date_range_type"):
+ self.env["date.range.type"].autogenerate_ranges()
+ self.assertFalse(dr_type.date_ranges_exist)
diff --git a/odex30_base/date_range/views/assets.xml b/odex30_base/date_range/views/assets.xml
new file mode 100644
index 0000000..7a86721
--- /dev/null
+++ b/odex30_base/date_range/views/assets.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/odex30_base/date_range/views/date_range_view.xml b/odex30_base/date_range/views/date_range_view.xml
new file mode 100644
index 0000000..243bdda
--- /dev/null
+++ b/odex30_base/date_range/views/date_range_view.xml
@@ -0,0 +1,161 @@
+
+
+
+ date.range.list
+ date.range
+
+
+
+
+
+
+
+
+
+
+
+
+ date.range.form
+ date.range
+
+
+
+
+
+ date.range.type.list
+ date.range.type
+
+
+
+
+
+
+
+
+
+
+ date.range.type.form
+ date.range.type
+
+
+
+
+
+ Date Ranges
+ date.range
+ list,form
+
+ []
+ {}
+
+
+ Date Range Types
+ date.range.type
+ list,form
+
+ []
+ {}
+
+
+
+
+
diff --git a/odex30_base/date_range/wizard/__init__.py b/odex30_base/date_range/wizard/__init__.py
new file mode 100644
index 0000000..bb07173
--- /dev/null
+++ b/odex30_base/date_range/wizard/__init__.py
@@ -0,0 +1,3 @@
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from . import date_range_generator
diff --git a/odex30_base/date_range/wizard/date_range_generator.py b/odex30_base/date_range/wizard/date_range_generator.py
new file mode 100644
index 0000000..4103612
--- /dev/null
+++ b/odex30_base/date_range/wizard/date_range_generator.py
@@ -0,0 +1,320 @@
+# Copyright 2016 ACSONE SA/NV ()
+# Copyright 2021 Opener B.V. ()
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from dateutil.relativedelta import relativedelta
+from dateutil.rrule import DAILY, MONTHLY, WEEKLY, YEARLY, rrule
+
+from odoo import _, api, fields, models
+from odoo.exceptions import UserError, ValidationError
+from odoo.tools.safe_eval import safe_eval
+
+
+class DateRangeGenerator(models.TransientModel):
+ _name = "date.range.generator"
+ _description = "Date Range Generator"
+
+ name_expr = fields.Text(
+ "Range name expression",
+ compute="_compute_name_expr",
+ readonly=False,
+ store=True,
+ help=(
+ "Evaluated expression. E.g. "
+ "\"'FY%s' % date_start.strftime('%Y%m%d')\"\nYou can "
+ "use the Date types 'date_end' and 'date_start', as well as "
+ "the 'index' variable."
+ ),
+ )
+ name_prefix = fields.Char(
+ "Range name prefix",
+ compute="_compute_name_prefix",
+ readonly=False,
+ store=True,
+ )
+ range_name_preview = fields.Char(compute="_compute_range_name_preview")
+ date_start = fields.Date(
+ "Start date",
+ compute="_compute_date_start",
+ readonly=False,
+ store=True,
+ required=True,
+ )
+ date_end = fields.Date("End date", compute="_compute_date_end", readonly=False)
+ type_id = fields.Many2one(
+ comodel_name="date.range.type",
+ string="Type",
+ required=True,
+ domain="['|', ('company_id', '=', company_id), " "('company_id', '=', False)]",
+ ondelete="cascade",
+ store=True,
+ compute="_compute_type_id",
+ readonly=False,
+ )
+ company_id = fields.Many2one(
+ comodel_name="res.company",
+ string="Company",
+ compute="_compute_company_id",
+ readonly=False,
+ store=True,
+ )
+ unit_of_time = fields.Selection(
+ [
+ (str(YEARLY), "years"),
+ (str(MONTHLY), "months"),
+ (str(WEEKLY), "weeks"),
+ (str(DAILY), "days"),
+ ],
+ compute="_compute_unit_of_time",
+ readonly=False,
+ store=True,
+ required=True,
+ )
+ duration_count = fields.Integer(
+ "Duration",
+ compute="_compute_duration_count",
+ readonly=False,
+ store=True,
+ required=True,
+ )
+ count = fields.Integer(
+ string="Number of ranges to generate",
+ )
+
+ @api.onchange("date_end")
+ def onchange_date_end(self):
+ if self.date_end and self.count:
+ self.count = 0
+
+ @api.onchange("count")
+ def onchange_count(self):
+ if self.count and self.date_end:
+ self.date_end = False
+
+ @api.onchange("name_expr")
+ def onchange_name_expr(self):
+ """Wipe the prefix if an expression is entered.
+
+ The reverse is not implemented because we don't want to wipe the
+ users' painstakingly crafted expressions by accident.
+ """
+ if self.name_expr and self.name_prefix:
+ self.name_prefix = False
+
+ @api.depends("company_id", "type_id.company_id")
+ def _compute_type_id(self):
+ if (
+ self.company_id
+ and self.type_id.company_id
+ and self.type_id.company_id != self.company_id
+ ):
+ self.type_id = self.env["date.range.type"]
+
+ def _generate_intervals(self, batch=False):
+ """Generate a list of dates representing the intervals.
+
+ The last date only serves to compute the end date of the last interval.
+
+ :param batch: When true, don't raise when there are no ranges to
+ generate.
+ """
+ if not self.date_end and not self.count:
+ if batch:
+ return []
+ raise ValidationError(
+ _("Please enter an end date, or the number of ranges to " "generate.")
+ )
+ kwargs = dict(
+ freq=int(self.unit_of_time),
+ interval=self.duration_count,
+ dtstart=self.date_start,
+ )
+ if self.date_end:
+ kwargs["until"] = self.date_end
+ else:
+ kwargs["count"] = self.count
+ vals = list(rrule(**kwargs))
+ if not vals:
+ raise UserError(_("No ranges to generate with these settings"))
+ # Generate another interval to fetch the last end date from
+ vals.append(
+ list(
+ rrule(
+ freq=int(self.unit_of_time),
+ interval=self.duration_count,
+ dtstart=vals[-1].date(),
+ count=2,
+ )
+ )[-1]
+ )
+ return vals
+
+ def generate_names(self, vals):
+ """Generate the names for the given intervals"""
+ self.ensure_one()
+ return self._generate_names(vals, self.name_expr, self.name_prefix)
+
+ @staticmethod
+ def _generate_names(vals, name_expr, name_prefix):
+ """Generate the names for the given intervals and naming parameters"""
+ names = []
+ count_digits = len(str(len(vals) - 1))
+ for idx, dt_start in enumerate(vals[:-1]):
+ date_start = dt_start.date()
+ # always remove 1 day for the date_end since range limits are
+ # inclusive
+ date_end = vals[idx + 1].date() - relativedelta(days=1)
+ index = "%0*d" % (count_digits, idx + 1)
+ if name_expr:
+ try:
+ names.append(
+ safe_eval(
+ name_expr,
+ {
+ "date_end": date_end,
+ "date_start": date_start,
+ "index": index,
+ },
+ )
+ )
+ except (SyntaxError, ValueError) as e:
+ raise ValidationError(_("Invalid name expression: %s") % e)
+ elif name_prefix:
+ names.append(name_prefix + index)
+ else:
+ raise ValidationError(
+ _(
+ "Please set a prefix or an expression to generate "
+ "the range names."
+ )
+ )
+ return names
+
+ @api.depends("name_expr", "name_prefix")
+ def _compute_range_name_preview(self):
+ for wiz in self:
+ preview = False
+ if wiz.name_expr or wiz.name_prefix:
+ vals = False
+ try:
+ vals = wiz._generate_intervals()
+ except Exception:
+ pass
+ if vals:
+ names = wiz.generate_names(vals)
+ if names:
+ preview = names[0]
+ wiz.range_name_preview = preview
+
+ def _generate_date_ranges(self, batch=False):
+ """Actually generate the date ranges."""
+ self.ensure_one()
+ vals = self._generate_intervals(batch=batch)
+ if not vals:
+ return []
+ date_ranges = []
+ names = self.generate_names(vals)
+ for idx, dt_start in enumerate(vals[:-1]):
+ date_start = dt_start.date()
+ date_end = vals[idx + 1].date() - relativedelta(days=1)
+ date_ranges.append(
+ {
+ "name": names[idx],
+ "date_start": date_start,
+ "date_end": date_end,
+ "type_id": self.type_id.id,
+ "company_id": self.company_id.id,
+ }
+ )
+ return date_ranges
+
+ @api.depends("type_id")
+ def _compute_company_id(self):
+ if self.type_id:
+ self.company_id = self.type_id.company_id
+ else:
+ self.company_id = self.env.company
+
+ @api.depends("type_id")
+ def _compute_name_expr(self):
+ if self.type_id.name_expr:
+ self.name_expr = self.type_id.name_expr
+
+ @api.depends("type_id")
+ def _compute_name_prefix(self):
+ if self.type_id.name_prefix:
+ self.name_prefix = self.type_id.name_prefix
+
+ @api.depends("type_id")
+ def _compute_duration_count(self):
+ if self.type_id.duration_count:
+ self.duration_count = self.type_id.duration_count
+
+ @api.depends("type_id")
+ def _compute_unit_of_time(self):
+ if self.type_id.unit_of_time:
+ self.unit_of_time = self.type_id.unit_of_time
+
+ @api.depends("type_id")
+ def _compute_date_start(self):
+ if not self.type_id:
+ return
+ last = self.env["date.range"].search(
+ [("type_id", "=", self.type_id.id)], order="date_end desc", limit=1
+ )
+ today = fields.Date.context_today(self)
+ if last:
+ self.date_start = last.date_end + relativedelta(days=1)
+ elif self.type_id.autogeneration_date_start:
+ self.date_start = self.type_id.autogeneration_date_start
+ else: # default to the beginning of the current year
+ self.date_start = today.replace(day=1, month=1)
+
+ @api.depends("date_start")
+ def _compute_date_end(self):
+ if not self.type_id or not self.date_start:
+ return
+ if self.type_id.autogeneration_unit and self.type_id.autogeneration_count:
+ key = {
+ str(YEARLY): "years",
+ str(MONTHLY): "months",
+ str(WEEKLY): "weeks",
+ str(DAILY): "days",
+ }[self.type_id.autogeneration_unit]
+ today = fields.Date.context_today(self)
+ date_end = today + relativedelta(**{key: self.type_id.autogeneration_count})
+ if date_end > self.date_start:
+ self.date_end = date_end
+
+ @api.onchange("company_id")
+ def _onchange_company_id(self):
+ if (
+ self.company_id
+ and self.type_id.company_id
+ and self.type_id.company_id != self.company_id
+ ):
+ self._cache.update(self._convert_to_cache({"type_id": False}, update=True))
+
+ @api.constrains("company_id", "type_id")
+ def _check_company_id_type_id(self):
+ for rec in self.sudo():
+ if (
+ rec.company_id
+ and rec.type_id.company_id
+ and rec.company_id != rec.type_id.company_id
+ ):
+ raise ValidationError(
+ _(
+ "The Company in the Date Range Generator and in "
+ "Date Range Type must be the same."
+ )
+ )
+
+ def action_apply(self, batch=False):
+ date_ranges = self._generate_date_ranges(batch=batch)
+ if date_ranges:
+ for dr in date_ranges:
+ self.env["date.range"].create(dr)
+ return self.env["ir.actions.actions"]._for_xml_id(
+ "date_range.date_range_action"
+ )
diff --git a/odex30_base/date_range/wizard/date_range_generator.xml b/odex30_base/date_range/wizard/date_range_generator.xml
new file mode 100644
index 0000000..40ca4f7
--- /dev/null
+++ b/odex30_base/date_range/wizard/date_range_generator.xml
@@ -0,0 +1,83 @@
+
+
+
+ date.range.generator.form
+ date.range.generator
+
+
+
+
+
+ Generate Date Ranges
+ date.range.generator
+ form
+
+ new
+
+
+
diff --git a/odex30_base/management_bugs/__init__.py b/odex30_base/management_bugs/__init__.py
new file mode 100644
index 0000000..5305644
--- /dev/null
+++ b/odex30_base/management_bugs/__init__.py
@@ -0,0 +1,3 @@
+# -*- coding: utf-8 -*-
+
+from . import models
\ No newline at end of file
diff --git a/odex30_base/management_bugs/__manifest__.py b/odex30_base/management_bugs/__manifest__.py
new file mode 100644
index 0000000..c7d1d0c
--- /dev/null
+++ b/odex30_base/management_bugs/__manifest__.py
@@ -0,0 +1,55 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# This module you will Support for Odoo Open source platform.
+# Error control and bug fixes.
+# It will process the data entered and return a message indicating whether
+# the company is eligible or not.
+#
+# Copyright (C) 2020- todooweb.com (https://www.todooweb.com)
+# @author ToDOO (https://www.linkedin.com/company/todooweb)
+#
+# 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 .
+#
+###############################################################################
+{
+ 'name': "System Bugs Management",
+ 'summary': """System Bugs Management""",
+ 'description': """
+ System Bugs Management. Error control and bug fixes in the Odoo Open source platform
+ """,
+ 'version': '18.0.2.1',
+ 'category': 'Tools',
+ 'license': 'LGPL-3',
+ 'author': "ToDOO (www.todooweb.com)",
+ 'website': "https://todooweb.com/",
+ 'contributors': [
+ "Equipo Dev ",
+ "Edgar Naranjo ",
+ "Tatiana Rosabal ",
+ ],
+ 'support': 'devtodoo@gmail.com',
+ 'depends': [
+ 'base',
+ 'project',
+ ],
+ 'data': [
+ 'security/ir.model.access.csv',
+ 'security/management_bug_security.xml',
+ 'views/management_bug.xml',
+ 'data/bugs_data.xml',
+ ],
+
+ 'images': [
+ 'static/description/screenshot_management_bug.png',
+ ],
+ 'installable': True,
+ 'application': True,
+ 'auto_install': False,
+}
diff --git a/odex30_base/management_bugs/data/bugs_data.xml b/odex30_base/management_bugs/data/bugs_data.xml
new file mode 100644
index 0000000..beb6bf4
--- /dev/null
+++ b/odex30_base/management_bugs/data/bugs_data.xml
@@ -0,0 +1,42 @@
+
+
+
+ Route log odoo
+ True
+ /var/log/odoo
+
+
+
+ Bugs and Issues
+ followers
+
+
+
+ Support Team
+
+
+
+ Development Team
+
+
+
+ QA Testing Team
+
+
+
+
+
+ Check Log System Odoo
+
+ code
+ model.action_check_all_bugs()
+
+
+
+
+
+ 30
+ minutes
+
+
+
\ No newline at end of file
diff --git a/odex30_base/management_bugs/i18n/es.po b/odex30_base/management_bugs/i18n/es.po
new file mode 100644
index 0000000..f22e5f7
--- /dev/null
+++ b/odex30_base/management_bugs/i18n/es.po
@@ -0,0 +1,330 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * management_bugs
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 10.0-20190207\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2020-04-06 17:31+0000\n"
+"PO-Revision-Date: 2020-04-06 17:31+0000\n"
+"Last-Translator: <>\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: \n"
+
+#. module: management_bugs
+#: model:ir.ui.view,arch_db:management_bugs.management_bug_assign_form
+#: model:ir.ui.view,arch_db:management_bugs.management_bug_assign_form_me
+msgid "Accept"
+msgstr "Aceptar"
+
+#. module: management_bugs
+#: model:ir.model.fields,field_description:management_bugs.field_configuration_bug_active
+#: model:ir.model.fields,field_description:management_bugs.field_management_bug_active
+msgid "Active"
+msgstr "Activo"
+
+#. module: management_bugs
+#: selection:management.bug.assign,type_assign:0
+msgid "Agent"
+msgstr "Agente"
+
+#. module: management_bugs
+#: model:ir.ui.menu,name:management_bugs.menu_projects_management_bug
+msgid "All Bugs"
+msgstr "Listado Bugs"
+
+#. module: management_bugs
+#: model:ir.actions.act_window,name:management_bugs.action_management_bug
+msgid "All bugs"
+msgstr "Listado bugs"
+
+#. module: management_bugs
+#: model:ir.model.fields,field_description:management_bugs.field_management_bug_assign_type_assign
+msgid "Assign"
+msgstr "Asignar"
+
+#. module: management_bugs
+#: model:ir.ui.view,arch_db:management_bugs.management_bug_form
+#: model:ir.ui.view,arch_db:management_bugs.management_bug_search
+#: model:ir.ui.view,arch_db:management_bugs.management_bug_tree
+msgid "Bugs"
+msgstr "Bugs"
+
+#. module: management_bugs
+#: model:ir.ui.view,arch_db:management_bugs.management_bug_form
+msgid "CLAIM"
+msgstr "RECLAMAR"
+
+#. module: management_bugs
+#: model:ir.ui.view,arch_db:management_bugs.management_bug_assign_form
+#: model:ir.ui.view,arch_db:management_bugs.management_bug_assign_form_me
+msgid "Cancel"
+msgstr "Cancelar"
+
+#. module: management_bugs
+#: model:ir.model.fields,field_description:management_bugs.field_management_bug_code
+msgid "Code"
+msgstr "Código"
+
+#. module: management_bugs
+#: model:ir.model,name:management_bugs.model_configuration_bug
+msgid "Configuration Bug"
+msgstr "Configuracion Bug"
+
+#. module: management_bugs
+#: model:ir.ui.view,arch_db:management_bugs.configuration_bug_form
+#: model:ir.ui.view,arch_db:management_bugs.configuration_bug_search
+#: model:ir.ui.view,arch_db:management_bugs.configuration_bug_tree
+msgid "Configuration bug"
+msgstr "Configuracion bug"
+
+#. module: management_bugs
+#: model:ir.model.fields,field_description:management_bugs.field_configuration_bug_create_uid
+#: model:ir.model.fields,field_description:management_bugs.field_management_bug_assign_create_uid
+#: model:ir.model.fields,field_description:management_bugs.field_management_bug_create_uid
+#: model:ir.model.fields,field_description:management_bugs.field_team_support_create_uid
+msgid "Created by"
+msgstr "Creado por"
+
+#. module: management_bugs
+#: model:ir.model.fields,field_description:management_bugs.field_configuration_bug_create_date
+#: model:ir.model.fields,field_description:management_bugs.field_management_bug_assign_create_date
+#: model:ir.model.fields,field_description:management_bugs.field_management_bug_create_date
+#: model:ir.model.fields,field_description:management_bugs.field_team_support_create_date
+msgid "Created on"
+msgstr "Creado el"
+
+#. module: management_bugs
+#: model:ir.model.fields,field_description:management_bugs.field_management_bug_date_error
+msgid "Date error"
+msgstr "Fecha error"
+
+#. module: management_bugs
+#: model:ir.model.fields,field_description:management_bugs.field_management_bug_description
+msgid "Description"
+msgstr "Descripción"
+
+#. module: management_bugs
+#: model:ir.model.fields,field_description:management_bugs.field_configuration_bug_display_name
+#: model:ir.model.fields,field_description:management_bugs.field_management_bug_assign_display_name
+#: model:ir.model.fields,field_description:management_bugs.field_management_bug_display_name
+#: model:ir.model.fields,field_description:management_bugs.field_team_support_display_name
+msgid "Display Name"
+msgstr "Nombre a mostrar"
+
+#. module: management_bugs
+#: code:addons/management_bugs/models/bug_digest.py:16
+#, python-format
+msgid "Do not have access, skip this data for user's digest email"
+msgstr "No tiene acceso, omita estos datos para el correo electrónico de resumen del usuario
+"
+
+#. module: management_bugs
+#: model:ir.ui.view,arch_db:management_bugs.management_bug_form
+msgid "Document Name"
+msgstr "Nombre documento"
+
+#. module: management_bugs
+#: selection:management.bug,type_bug:0
+msgid "Error"
+msgstr "Error"
+
+#. module: management_bugs
+#: model:ir.model.fields,field_description:management_bugs.field_management_bug_hour_error
+msgid "Hours"
+msgstr "Horas"
+
+#. module: management_bugs
+#: model:ir.model.fields,field_description:management_bugs.field_configuration_bug_id
+#: model:ir.model.fields,field_description:management_bugs.field_management_bug_assign_id
+#: model:ir.model.fields,field_description:management_bugs.field_management_bug_id
+#: model:ir.model.fields,field_description:management_bugs.field_team_support_id
+msgid "ID"
+msgstr "ID"
+
+#. module: management_bugs
+#: model:ir.model.fields,field_description:management_bugs.field_configuration_bug___last_update
+#: model:ir.model.fields,field_description:management_bugs.field_management_bug___last_update
+#: model:ir.model.fields,field_description:management_bugs.field_management_bug_assign___last_update
+#: model:ir.model.fields,field_description:management_bugs.field_team_support___last_update
+msgid "Last Modified on"
+msgstr "Última modificación en"
+
+#. module: management_bugs
+#: model:ir.model.fields,field_description:management_bugs.field_configuration_bug_write_uid
+#: model:ir.model.fields,field_description:management_bugs.field_management_bug_assign_write_uid
+#: model:ir.model.fields,field_description:management_bugs.field_management_bug_write_uid
+#: model:ir.model.fields,field_description:management_bugs.field_team_support_write_uid
+msgid "Last Updated by"
+msgstr "Última actualización por"
+
+#. module: management_bugs
+#: model:ir.model.fields,field_description:management_bugs.field_configuration_bug_write_date
+#: model:ir.model.fields,field_description:management_bugs.field_management_bug_assign_write_date
+#: model:ir.model.fields,field_description:management_bugs.field_management_bug_write_date
+#: model:ir.model.fields,field_description:management_bugs.field_team_support_write_date
+msgid "Last Updated on"
+msgstr "Última actualización el"
+
+#. module: management_bugs
+#: model:ir.model.fields,field_description:management_bugs.field_team_support_leader_id
+msgid "Leader"
+msgstr "Jefe de equipo"
+
+#. module: management_bugs
+#: model:ir.model.fields,field_description:management_bugs.field_management_bug_line
+msgid "Line"
+msgstr "Linea"
+
+#. module: management_bugs
+#: model:ir.ui.menu,name:management_bugs.menu_projects_all_bugs
+msgid "Management Bugs"
+msgstr "Administrar Bugs"
+
+#. module: management_bugs
+#: model:ir.model,name:management_bugs.model_management_bug
+msgid "Management bug"
+msgstr "Administrar bug"
+
+#. module: management_bugs
+#: model:ir.model,name:management_bugs.model_management_bug_assign
+#: model:ir.ui.view,arch_db:management_bugs.management_bug_assign_form
+#: model:ir.ui.view,arch_db:management_bugs.management_bug_assign_form_me
+#: model:ir.ui.view,arch_db:management_bugs.management_bug_assign_tree
+msgid "Management bug assign"
+msgstr "Administrar asignacion bug"
+
+#. module: management_bugs
+#: model:ir.model.fields,field_description:management_bugs.field_team_support_member_ids
+msgid "Members"
+msgstr "Socios"
+
+#. module: management_bugs
+#: model:ir.model.fields,field_description:management_bugs.field_configuration_bug_name
+#: model:ir.model.fields,field_description:management_bugs.field_management_bug_name
+#: model:ir.model.fields,field_description:management_bugs.field_team_support_name
+msgid "Name"
+msgstr "Nombre"
+
+#. module: management_bugs
+#: model:ir.model.fields,field_description:management_bugs.field_management_bug_assign_note
+msgid "Note"
+msgstr "Nota"
+
+#. module: management_bugs
+#: model:ir.model.fields,field_description:management_bugs.field_management_bug_note
+msgid "Notes"
+msgstr "Notas"
+
+#. module: management_bugs
+#: model:ir.ui.view,arch_db:management_bugs.management_bug_form
+msgid "Other data"
+msgstr "Otros datos"
+
+#. module: management_bugs
+#: model:ir.model.fields,field_description:management_bugs.field_management_bug_assign_project_id
+#: model:ir.model.fields,field_description:management_bugs.field_management_bug_project_id
+msgid "Projects"
+msgstr "Proyectos"
+
+#. module: management_bugs
+#: model:ir.ui.view,arch_db:management_bugs.management_bug_search
+#: selection:management.bug,state:0
+msgid "Resolved"
+msgstr "Resuelta"
+
+#. module: management_bugs
+#: model:ir.model.fields,field_description:management_bugs.field_configuration_bug_route
+msgid "Route"
+msgstr "Ruta"
+
+#. module: management_bugs
+#: model:configuration.bug,name:management_bugs.configuration01
+msgid "Route log odoo"
+msgstr "Ruta log odoo"
+
+#. module: management_bugs
+#: model:ir.actions.act_window,name:management_bugs.action_configuration_bug
+#: model:ir.ui.menu,name:management_bugs.menu_projects_configuration_bug
+msgid "Setting"
+msgstr "Configracion"
+
+#. module: management_bugs
+#: model:ir.model.fields,field_description:management_bugs.field_management_bug_state
+msgid "Status"
+msgstr "Estado"
+
+#. module: management_bugs
+#: model:ir.ui.view,arch_db:management_bugs.management_bug_form
+msgid "TRANSFER / ASIGN"
+msgstr "TRANSFERIR / ASIGNAR"
+
+#. module: management_bugs
+#: model:ir.model,name:management_bugs.model_project_task
+msgid "Task"
+msgstr "Tarea"
+
+#. module: management_bugs
+#: model:ir.ui.view,arch_db:management_bugs.team_support_form
+msgid "Team Members"
+msgstr "Miembros equipo"
+
+#. module: management_bugs
+#: model:ir.model.fields,field_description:management_bugs.field_management_bug_assign_support_id
+#: model:ir.model.fields,field_description:management_bugs.field_project_task_support_id
+#: selection:management.bug.assign,type_assign:0
+msgid "Team Support"
+msgstr "Equipo soporte"
+
+#. module: management_bugs
+#: model:ir.actions.act_window,name:management_bugs.action_team_support
+#: model:ir.model,name:management_bugs.model_team_support
+#: model:ir.ui.menu,name:management_bugs.menu_projects_team_support
+#: model:ir.ui.view,arch_db:management_bugs.team_support_form
+#: model:ir.ui.view,arch_db:management_bugs.team_support_search
+#: model:ir.ui.view,arch_db:management_bugs.team_support_tree
+msgid "Team support"
+msgstr "Equipo soporte"
+
+#. module: management_bugs
+#: model:ir.model.fields,help:management_bugs.field_configuration_bug_route
+msgid "The path to the file should contain the container folders, Ex: /var/log/.."
+msgstr "La ruta al archivo debe contener las carpetas del contenedor, Ej: / var / log / .."
+
+#. module: management_bugs
+#: code:addons/management_bugs/models/management_bug.py:230
+#, python-format
+msgid "The support team does not has a members"
+msgstr "El equipo de soporte no tiene miembros"
+
+#. module: management_bugs
+#: code:addons/management_bugs/models/management_bug.py:228
+#, python-format
+msgid "The support team does not has a team leader"
+msgstr "El equipo de soporte no tiene una líder de equipo"
+
+#. module: management_bugs
+#: model:ir.model.fields,field_description:management_bugs.field_management_bug_type_bug
+msgid "Type Bug"
+msgstr "Tipo Bug"
+
+#. module: management_bugs
+#: model:ir.ui.view,arch_db:management_bugs.management_bug_search
+#: selection:management.bug,state:0
+msgid "Unresolved"
+msgstr "No resuelta"
+
+#. module: management_bugs
+#: model:ir.model.fields,field_description:management_bugs.field_management_bug_assign_user_id
+msgid "User"
+msgstr "Usuario"
+
+#. module: management_bugs
+#: selection:management.bug,type_bug:0
+msgid "Warning"
+msgstr "Warning"
+
diff --git a/odex30_base/management_bugs/models/__init__.py b/odex30_base/management_bugs/models/__init__.py
new file mode 100644
index 0000000..f0db629
--- /dev/null
+++ b/odex30_base/management_bugs/models/__init__.py
@@ -0,0 +1,2 @@
+# -*- coding: utf-8 -*-
+from . import management_bug
diff --git a/odex30_base/management_bugs/models/management_bug.py b/odex30_base/management_bugs/models/management_bug.py
new file mode 100644
index 0000000..05f050c
--- /dev/null
+++ b/odex30_base/management_bugs/models/management_bug.py
@@ -0,0 +1,282 @@
+# -*- coding: utf-8 -*-
+import glob
+import os
+import shutil
+
+from odoo import api, fields, models, tools, SUPERUSER_ID, _
+from odoo.exceptions import UserError, AccessError, ValidationError
+
+
+class ManagementBug(models.Model):
+ _name = 'management.bug'
+ _description = 'Management bug'
+ _order = 'id'
+
+ name = fields.Char(string='Name', required=True, translate=True)
+ code = fields.Char('Code')
+ date_error = fields.Date('Date error')
+ hour_error = fields.Char('Hours')
+ description = fields.Text('Description')
+ type_bug = fields.Selection([
+ ('error', 'Error'),
+ ('warning', 'Warning')], 'Type Bug', track_visibility='always', default=lambda self: self._context.get('type', 'warning'))
+ line = fields.Char('Line')
+ project_id = fields.Many2one('project.project', 'Projects', track_visibility='onchange')
+ active = fields.Boolean('Active', default=True)
+ state = fields.Selection([
+ ('unresolved', 'Unresolved'),
+ ('resolved', 'Resolved')], 'Status', track_visibility='onchage', default='unresolved')
+ note = fields.Text('Notes')
+
+ def read_route_file(self, route):
+ name_route = ''
+ if glob.glob(route + '/*'):
+ list_path = glob.glob(route + '/*.log')
+ for name in list_path:
+ separate_name = name.split('/')[-1:]
+ if separate_name[0] == 'odoo.log':
+ name_route = name
+ return name_route
+
+ def action_check_all_bugs(self):
+ dict_error = {
+ 'name': '',
+ 'code': '',
+ 'date_error': False,
+ 'hour_error': False,
+ 'description': '',
+ 'type_bug': False,
+ 'line': ''
+ }
+ dict_init = {
+ 'name': '',
+ 'code': '',
+ 'date_error': False,
+ 'hour_error': False,
+ 'description': '',
+ 'type_bug': False,
+ 'line': ''
+ }
+ details_line = 0
+ name_error = 'ERROR-'
+ name_warn = 'WARNING-'
+ list_display = []
+ # data configuration
+ obj_setting_id = self.env['configuration.bug'].search([('active', '=', True)])
+ if obj_setting_id:
+ for obj_setting in obj_setting_id:
+ route = obj_setting.route
+ file_touch = self.read_route_file(route)
+ if file_touch:
+ # copy log
+ destination_route = '/tmp/' + 'new_log.log'
+ if os.path.exists(file_touch):
+ with open(file_touch, 'rb') as forigen:
+ with open(destination_route, 'wb') as fdestino:
+ shutil.copyfileobj(forigen, fdestino)
+ # read log new
+ if os.path.exists(destination_route):
+ file_lines = open(destination_route, 'r')
+ for line in file_lines:
+ details_line += 1
+ count_character = 0
+ line = line.split(' ')
+ if 'ERROR' in line or 'WARNING' in line:
+ dict_error['date_error'] = line[0]
+ dict_error['hour_error'] = line[1]
+ dict_error['code'] = line[2]
+ dict_error['description'] = line[-1]
+ dict_error['line'] = details_line
+ if 'ERROR' in line:
+ dict_error['name'] = name_error + line[2]
+ dict_error['type_bug'] = 'error'
+ for i in line:
+ list_display = line
+ if i != 'ERROR':
+ count_character += 1
+ if count_character <= 4:
+ list_display.pop(0)
+ dict_error['description'] = " ".join(list_display)
+ else:
+ dict_error['name'] = name_warn + line[2]
+ dict_error['type_bug'] = 'warning'
+ for i in line:
+ list_display = line
+ if i != 'WARNING':
+ count_character += 1
+ if count_character <= 4:
+ list_display.pop(0)
+ dict_error['description'] = " ".join(list_display)
+ create_bug = self.env['management.bug']
+ # create model (data)
+ if len(dict_error) > 0:
+ # eliminar los que tengan valor False
+ dict_error = dict(filter(lambda x: x[1] != False, dict_error.items()))
+ # crear bug
+ create_bug.create(dict_error)
+ dict_error.update(dict_init)
+ # delete new log
+ file_lines.close()
+ os.remove(destination_route)
+
+ def action_claim_bug(self):
+ self.ensure_one()
+ ir_model_data = self.env['ir.model.data']
+ try:
+ compose_form_id = ir_model_data._xmlid_to_res_id('management_bugs.management_bug_assign_form')
+ except ValueError:
+ compose_form_id = False
+ return {
+ "name": "Claim a Bugs",
+ "view_type": "form",
+ "view_mode": "form",
+ "res_model": "management.bug.assign",
+ "type": "ir.actions.act_window",
+ 'view_id': compose_form_id,
+ 'target': 'new',
+ }
+
+ def action_to_assign_bug(self):
+ self.ensure_one()
+ ir_model_data = self.env['ir.model.data']
+ try:
+ compose_form_id = ir_model_data._xmlid_to_res_id('management_bugs.management_bug_assign_form')
+
+ except ValueError:
+ compose_form_id = False
+ return {
+ "name": "Transfer or Assign",
+ "view_type": "form",
+ "view_mode": "form",
+ "res_model": "management.bug.assign",
+ "type": "ir.actions.act_window",
+ 'view_id': compose_form_id,
+ 'target': 'new',
+ }
+
+
+class ConfigurationBug(models.Model):
+ _name = "configuration.bug"
+ _description = "Configuration Bug"
+
+ name = fields.Char(string='Name', required=True, translate=True)
+ active = fields.Boolean('Active')
+ route = fields.Char('Route', required=True, help='The path to the file should contain the container folders, Ex: /var/log/..')
+
+ @api.constrains('route')
+ def _add_constrains_fields(self):
+ if self.route:
+ if not self.route == '/var/log/odoo':
+ raise ValidationError("The route of the file should are '/var/log/odoo' .")
+
+
+class ManagementBugAssign(models.TransientModel):
+ _name = "management.bug.assign"
+ _description = "Management bug assign"
+ _rec_name = 'type_assign'
+
+ type_assign = fields.Selection([
+ ('agent', 'Agent'),
+ ('team', 'Team Support')], 'Assign', track_visibility='onchage', default='agent', required=True, index=True)
+ user_id = fields.Many2one('res.users', 'User')
+ support_id = fields.Many2one('team.support', 'Team Support')
+ project_id = fields.Many2one('project.project', 'Projects', track_visibility='onchange')
+ note = fields.Text('Note')
+
+ def action_do_transfer(self):
+ self.ensure_one()
+ dict_task = {
+ 'name': '',
+ 'project_id': '',
+ 'user_ids': '',
+ 'support_id': '',
+ 'description': ''
+ }
+ name_task = ''
+ active_bug_ids = self.env.context.get('active_ids', [])
+ for bug in self.env['management.bug'].sudo().browse(active_bug_ids):
+ # make sure that each bug appears at most once in the list
+ if self.note:
+ if not bug.note:
+ bug.note = ''
+ bug.note += str(self.env.user.name) + ': ' + self.note + ' \n' + ' \n'
+ create_task = self.env['project.task']
+ if bug.type_bug:
+ if bug.type_bug == 'error':
+ name_task = '[Develop] ' + bug.name
+ if bug.type_bug == 'warning':
+ name_task = '[Support] ' + bug.name
+ dict_task['name'] = name_task
+ if self.project_id:
+ for project in self.env['project.project'].sudo().browse(self.project_id):
+ dict_task['project_id'] = project.id['id']
+ if self.project_id.user_id:
+ obj_support_id = self.env['team.support'].search([('leader_id', '=', self.project_id.user_id.id)])
+ if obj_support_id:
+ for support in obj_support_id:
+ list_members = support.member_ids
+ if list_members:
+ if self.user_id in list_members:
+ if self.type_assign == 'agent':
+ dict_task['user_ids'] = [(6, 0, [self.user_id.id])]
+ dict_task['support_id'] = support.id
+ # else:
+ # raise UserError(_('The support team does not has a team leader'))
+ # else:
+ # raise UserError(_('The support team does not has a members'))
+
+ if self.support_id:
+ obj_support_id = self.env['team.support'].search([('id', '=', self.support_id.id)])
+ if obj_support_id:
+ for obj_support in obj_support_id:
+ dict_task['support_id'] = obj_support.id
+ dict_task['user_ids'] = [(6, 0, [self.project_id.user_id.id])]
+ dict_task['description'] = bug.description
+ create_task.create(dict_task)
+ bug.state = 'resolved'
+
+ def action_do_claim(self):
+ self.ensure_one()
+ dict_task = {
+ 'name': '',
+ 'project_id': '',
+ 'user_id': '',
+ 'description': ''
+ }
+ name_task = ''
+ active_bug_ids = self.env.context.get('active_ids', [])
+ for bug in self.env['management.bug'].sudo().browse(active_bug_ids):
+ # make sure that each bug appears at most once in the list
+ if self.note:
+ if not bug.note:
+ bug.note = ''
+ bug.note += str(self.env.user.name) + ': ' + self.note + ' \n' + ' \n'
+ create_task = self.env['project.task']
+ if bug.type_bug:
+ if bug.type_bug == 'error':
+ name_task = '[Develop] ' + bug.name
+ if bug.type_bug == 'warning':
+ name_task = '[Support] ' + bug.name
+ dict_task['name'] = name_task
+ if self.project_id:
+ for project in self.env['project.project'].sudo().browse(self.project_id):
+ dict_task['project_id'] = project.id['id']
+ dict_task['user_id'] = self.env.user.id
+ dict_task['description'] = bug.description
+ create_task.create(dict_task)
+ bug.state = 'resolved'
+
+
+class TeamSupport(models.Model):
+ _name = 'team.support'
+ _description = 'Team support'
+
+ name = fields.Char('Name', index=True, required=True)
+ leader_id = fields.Many2one('res.users', 'Leader')
+ member_ids = fields.Many2many('res.users', 'team_user_support_rel', 'support_id', 'user_id', 'Members')
+
+
+class Task(models.Model):
+ _inherit = "project.task"
+
+ support_id = fields.Many2one('team.support', 'Team Support')
diff --git a/odex30_base/management_bugs/security/ir.model.access.csv b/odex30_base/management_bugs/security/ir.model.access.csv
new file mode 100644
index 0000000..d294df3
--- /dev/null
+++ b/odex30_base/management_bugs/security/ir.model.access.csv
@@ -0,0 +1,5 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+access_management_bug,access_management_bug,model_management_bug,project.group_project_manager,1,1,1,1
+access_configuration_bug,access_configuration_bug,model_configuration_bug,project.group_project_manager,1,1,1,1
+access_team_support,access_team_support,model_team_support,project.group_project_manager,1,1,1,1
+access_management_bug_assign,access_management_bug_assign,model_management_bug_assign,project.group_project_manager,1,1,1,1
\ No newline at end of file
diff --git a/odex30_base/management_bugs/security/management_bug_security.xml b/odex30_base/management_bugs/security/management_bug_security.xml
new file mode 100755
index 0000000..d8b5cce
--- /dev/null
+++ b/odex30_base/management_bugs/security/management_bug_security.xml
@@ -0,0 +1,28 @@
+
+
+
+
+ Management bug all user
+
+ [(1, '=', 1)]
+
+
+
+ Configuration bug all user
+
+ [(1, '=', 1)]
+
+
+
+ Team Support all user
+
+ [(1, '=', 1)]
+
+
+
+ Management Bug Assign all user
+
+ [(1, '=', 1)]
+
+
+
diff --git a/odex30_base/management_bugs/static/description/icon.png b/odex30_base/management_bugs/static/description/icon.png
new file mode 100644
index 0000000..4047a5a
Binary files /dev/null and b/odex30_base/management_bugs/static/description/icon.png differ
diff --git a/odex30_base/management_bugs/static/description/index.html b/odex30_base/management_bugs/static/description/index.html
new file mode 100644
index 0000000..24f60a5
--- /dev/null
+++ b/odex30_base/management_bugs/static/description/index.html
@@ -0,0 +1,77 @@
+
+
+
+
+
+
+ Management System Bugs. Error control and bug fixes in the Odoo Open source platform.
+
+
+
For this module helps to manage bugs in "Project" module:
+
+ Offers the ability to keep track of the bug.
+ You can see number of bugs assigned to the employee.
+ The automatics task generate and contact.
+ Manage team support and members.
+ A cron that runs every 30 min reading the odoo ".log".
+ Classify bugs into "error" and "warning".
+ Bugs are generated in the "All bugs" menu.
+ Once the bugs are generated, the tasks corresponding to a support team or agent are generated.
+ You can "Transfer", "Assign" or "Claim" a bug. Generating a new task associated with a Support Team or Agent.
+
+
+
+
+
Key Features:
+
+ Issues
+ Stages
+ Bugs assigned to employee in kanban and tree view
+
+
+
+
+
+
Our Services
+
+
+
+
+
Help and Support
+
Feel free to contact us, if you need any help with your Odoo integration or addiontal features.
+
+
+
+
+
+
diff --git a/odex30_base/management_bugs/static/description/logo.png b/odex30_base/management_bugs/static/description/logo.png
new file mode 100644
index 0000000..6f08586
Binary files /dev/null and b/odex30_base/management_bugs/static/description/logo.png differ
diff --git a/odex30_base/management_bugs/static/description/odoo-customization.png b/odex30_base/management_bugs/static/description/odoo-customization.png
new file mode 100644
index 0000000..9428b37
Binary files /dev/null and b/odex30_base/management_bugs/static/description/odoo-customization.png differ
diff --git a/odex30_base/management_bugs/static/description/odoo-implementation.png b/odex30_base/management_bugs/static/description/odoo-implementation.png
new file mode 100644
index 0000000..ce95b21
Binary files /dev/null and b/odex30_base/management_bugs/static/description/odoo-implementation.png differ
diff --git a/odex30_base/management_bugs/static/description/odoo-integration.png b/odex30_base/management_bugs/static/description/odoo-integration.png
new file mode 100644
index 0000000..8772651
Binary files /dev/null and b/odex30_base/management_bugs/static/description/odoo-integration.png differ
diff --git a/odex30_base/management_bugs/static/description/screenshot_management_bug.png b/odex30_base/management_bugs/static/description/screenshot_management_bug.png
new file mode 100644
index 0000000..a9f588a
Binary files /dev/null and b/odex30_base/management_bugs/static/description/screenshot_management_bug.png differ
diff --git a/odex30_base/management_bugs/views/management_bug.xml b/odex30_base/management_bugs/views/management_bug.xml
new file mode 100644
index 0000000..b3581af
--- /dev/null
+++ b/odex30_base/management_bugs/views/management_bug.xml
@@ -0,0 +1,316 @@
+
+
+
+
+
+ project.project.inherit.form
+ project.project
+
+
+
+ True
+
+
+
+
+
+
+ project.task.inherit.form
+ project.task
+
+
+
+
+
+
+
+
+
+
+
+ management.bug.form
+ management.bug
+
+
+
+
+
+
+
+ management.bug.list
+ management.bug
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ management.bug.search
+ management.bug
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ All bugs
+ management.bug
+ list,form
+
+ {'search_default_unresolved': 1}
+
+
+
+
+ configuration.bug.form
+ configuration.bug
+
+
+
+
+
+
+
+ configuration.bug.list
+ configuration.bug
+
+
+
+
+
+
+
+
+
+
+
+ configuration.bug.search
+ configuration.bug
+
+
+
+
+
+
+
+
+ Setting
+ configuration.bug
+ list,form
+
+
+
+
+
+
+ management.bug.assign.form
+ management.bug.assign
+
+
+
+
+
+
+
+ management.bug.assign.me.form
+ management.bug.assign
+
+
+
+
+
+
+
+
+
+ management.bug.assign.list
+ management.bug.assign
+
+
+
+
+
+
+
+
+
+ team.support.form
+ team.support
+
+
+
+
+
+
+
+ team.support.list
+ team.support
+
+
+
+
+
+
+
+
+
+
+ team.support.search
+ team.support
+
+
+
+
+
+
+
+
+
+ Team support
+ team.support
+ list,form
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/odex30_base/odex30_debrand/__init__.py b/odex30_base/odex30_debrand/__init__.py
new file mode 100644
index 0000000..c3d410e
--- /dev/null
+++ b/odex30_base/odex30_debrand/__init__.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8 -*-
+
+from . import models
+from . import controllers
diff --git a/odex30_base/odex30_debrand/__manifest__.py b/odex30_base/odex30_debrand/__manifest__.py
new file mode 100644
index 0000000..ab095ce
--- /dev/null
+++ b/odex30_base/odex30_debrand/__manifest__.py
@@ -0,0 +1,47 @@
+{
+ 'name': "Odex30- Debrand",
+
+ 'summary': """
+ Odoo Module for backend and frontend debranding.""",
+
+ 'description': """
+ To debrand front-end and back-end pages by removing
+ odoo promotions, links, labels and other related
+ stuffs.
+ """,
+
+ 'author': "Expert Co. Ltd.",
+ 'website': "http://www.exp-sa.com",
+ "category": "Odex30-base",
+ 'depends': [
+ 'base_setup',
+ 'website',
+ ],
+ 'data': [
+ 'security/ir.model.access.csv',
+ 'views/assets.xml',
+ 'views/mail_template_remove_odoo_views.xml',
+ 'views/website_footer_brand_promotion.xml',
+ 'views/ir_ui_menu.xml',
+ 'views/res_config_settings_views.xml',
+ 'views/login_image.xml',
+ 'templates/left_login_template.xml',
+ 'templates/right_login_template.xml',
+ 'templates/middle_login_template.xml',
+ 'templates/assets.xml',
+ 'views/portal_template.xml',
+ 'views/webclient_templates.xml'
+ ],
+ 'assets': {
+ 'web.assets_backend': [
+ 'odex30_debrand/static/src/js/favicon.js',
+ ],
+ 'web.assets_frontend': [
+ 'odex30_debrand/static/src/css/web_login_style.css',
+ ],
+ },
+ 'qweb': ['static/src/xml/base.xml'],
+ 'license': "AGPL-3",
+ 'installable': True,
+ 'application': False,
+}
diff --git a/odex30_base/odex30_debrand/controllers/__init__.py b/odex30_base/odex30_debrand/controllers/__init__.py
new file mode 100644
index 0000000..f2a5252
--- /dev/null
+++ b/odex30_base/odex30_debrand/controllers/__init__.py
@@ -0,0 +1,3 @@
+# -*- encoding: utf-8 -*-
+
+from . import main
diff --git a/odex30_base/odex30_debrand/controllers/main.py b/odex30_base/odex30_debrand/controllers/main.py
new file mode 100644
index 0000000..aba2139
--- /dev/null
+++ b/odex30_base/odex30_debrand/controllers/main.py
@@ -0,0 +1,188 @@
+# -*- encoding: utf-8 -*-
+
+import logging
+import werkzeug.exceptions
+import werkzeug.utils
+from werkzeug.urls import iri_to_uri
+import odoo
+from odoo.tools.translate import _
+from odoo import http, tools
+from odoo.http import request, Response
+from werkzeug.utils import redirect
+
+_logger = logging.getLogger(__name__)
+
+# ----------------------------------------------------------
+# Odoo Web helpers
+# ----------------------------------------------------------
+
+db_monodb = request._get_session_and_dbname
+
+
+# override
+def _get_login_redirect_url(uid, redirect=None):
+ """ Decide if user requires a specific post-login redirect, e.g. for 2FA, or if they are
+ fully logged and can proceed to the requested URL
+ """
+ if request.session.uid: # fully logged
+ return redirect or '/web'
+
+ # partial session (MFA)
+ url = request.env(user=uid)['res.users'].browse(uid)._mfa_url()
+ if not redirect:
+ return url
+
+ parsed = werkzeug.urls.url_parse(url)
+ qs = parsed.decode_query()
+ qs['redirect'] = redirect
+ return parsed.replace(query=werkzeug.urls.url_encode(qs)).to_url()
+
+
+# override
+def abort_and_redirect(url):
+ r = request.httprequest
+ response = werkzeug.utils.redirect(url, 302)
+ response = r.app.get_response(r, response, explicit_session=False)
+ werkzeug.exceptions.abort(response)
+
+
+# override
+def ensure_db(redirect='/web/database/selector'):
+ db = request.params.get('db') and request.params.get('db').strip()
+
+ # Ensure db is legit
+ if db and db not in http.db_filter([db]):
+ db = None
+
+ if db and not request.session.db:
+ # User asked a specific database on a new session.
+ # That mean the nodb router has been used to find the route
+ # Depending on installed module in the database, the rendering of the page
+ # may depend on data injected by the database route dispatcher.
+ # Thus, we redirect the user to the same page but with the session cookie set.
+ # This will force using the database route dispatcher...
+ r = request.httprequest
+ url_redirect = werkzeug.urls.url_parse(r.base_url)
+ if r.query_string:
+ # in P3, request.query_string is bytes, the rest is text, can't mix them
+ query_string = iri_to_uri(r.query_string)
+ url_redirect = url_redirect.replace(query=query_string)
+ request.session.db = db
+ abort_and_redirect(url_redirect)
+
+ # if db not provided, use the session one
+ if not db and request.session.db and http.db_filter([request.session.db]):
+ db = request.session.db
+
+ # if no database provided and no database in session, use monodb
+ if not db:
+ db = db_monodb(request.httprequest)
+
+ # if no db can be found til here, send to the database selector
+ # the database selector will redirect to database manager if needed
+ if not db:
+ werkzeug.exceptions.abort(werkzeug.utils.redirect(redirect, 303))
+
+ # always switch the session to the computed db
+ if db != request.session.db:
+ request.session.logout()
+ abort_and_redirect(request.httprequest.url)
+
+ request.session.db = db
+
+# ----------------------------------------------------------
+# Odoo Web web Controllers
+# ----------------------------------------------------------
+
+
+class Home(http.Controller):
+
+ # override
+ def _login_redirect(self, uid, redirect=None):
+ return _get_login_redirect_url(uid, redirect)
+
+ # override
+ @http.route('/web/login', type='http', auth="none")
+ def web_login(self, redirect=None, **kw):
+ ensure_db()
+ request.params['login_success'] = False
+ if request.httprequest.method == 'GET' and redirect and request.session.uid:
+ return request.redirect(redirect)
+
+ if not request.uid:
+ request.uid = odoo.SUPERUSER_ID
+
+ values = request.params.copy()
+ try:
+ values['databases'] = http.db_list()
+ except odoo.exceptions.AccessDenied:
+ values['databases'] = None
+
+ if request.httprequest.method == 'POST':
+ old_uid = request.uid
+ try:
+ credential = {
+ 'login': request.params.get('login'),
+ 'password': request.params.get('password'),
+ 'type': 'password'
+ }
+ auth_info = request.session.authenticate(request.session.db, credential)
+ uid = auth_info['uid']
+ request.params['login_success'] = True
+ return request.redirect(self._login_redirect(uid, redirect=redirect))
+ except odoo.exceptions.AccessDenied as e:
+ # request.uid = old_uid
+ request.update_env(user=old_uid)
+ if e.args == odoo.exceptions.AccessDenied().args:
+ values['error'] = _("Wrong login/password")
+ else:
+ values['error'] = e.args[0]
+ else:
+ if 'error' in request.params and request.params.get('error') == 'access':
+ values['error'] = _('Only employees can access this database. Please contact the administrator.')
+
+ if 'login' not in values and request.session.get('auth_login'):
+ values['login'] = request.session.get('auth_login')
+
+ if not odoo.tools.config['list_db']:
+ values['disable_database_manager'] = True
+
+ param_obj = request.env['ir.config_parameter'].sudo()
+ values['reset_password_enabled'] = param_obj.get_param('auth_signup.reset_password')
+ values['signup_enabled'] = param_obj.get_param('auth_signup.invitation_scope') == 'b2c'
+ values['disable_footer'] = param_obj.get_param('disable_footer')
+ style = param_obj.get_param('login_background.style')
+ background = param_obj.get_param('login_background.background')
+ values['background_color'] = param_obj.get_param('login_background.color')
+ background_image = param_obj.get_param('login_background.background_image')
+
+ if background == 'image':
+ image_url = ''
+ if background_image:
+ base_url = param_obj.get_param('web.base.url')
+ image_url = base_url + '/web/image?' + 'model=login.image&id=' + background_image + '&field=image'
+ values['background_src'] = image_url or ''
+ values['background_color'] = ''
+
+ if background == 'color':
+ values['background_src'] = ''
+
+ if style == 'default' or style is False:
+ response = request.render('web.login', values)
+ elif style == 'left':
+ response = request.render('odex30_debrand.left_login_template', values)
+ elif style == 'right':
+ response = request.render('odex30_debrand.right_login_template', values)
+ else:
+ response = request.render('odex30_debrand.middle_login_template', values)
+
+ response.headers['X-Frame-Options'] = 'DENY'
+ return response
+
+
+class Website(Home):
+
+ # override
+ @http.route(website=True, auth="public", sitemap=False)
+ def web_login(self, *args, **kw):
+ return super().web_login(*args, **kw)
diff --git a/odex30_base/odex30_debrand/models/__init__.py b/odex30_base/odex30_debrand/models/__init__.py
new file mode 100644
index 0000000..d489137
--- /dev/null
+++ b/odex30_base/odex30_debrand/models/__init__.py
@@ -0,0 +1,7 @@
+# -*- coding: utf-8 -*-
+
+from . import mail_template
+from . import login_image
+
+from . import publisher_warranty_contract
+from . import res_config_settings
diff --git a/odex30_base/odex30_debrand/models/login_image.py b/odex30_base/odex30_debrand/models/login_image.py
new file mode 100644
index 0000000..5b3b19f
--- /dev/null
+++ b/odex30_base/odex30_debrand/models/login_image.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+from odoo import models, fields, api, _
+
+
+class LoginImage(models.Model):
+ _name = 'login.image'
+ _rec_name = 'name'
+
+ image = fields.Binary(string="Image")
+ name = fields.Char(string="Name")
diff --git a/odex30_base/odex30_debrand/models/mail_template.py b/odex30_base/odex30_debrand/models/mail_template.py
new file mode 100644
index 0000000..2166074
--- /dev/null
+++ b/odex30_base/odex30_debrand/models/mail_template.py
@@ -0,0 +1,40 @@
+from bs4 import BeautifulSoup
+from odoo import models, fields, api, _
+
+class YourModel(models.Model):
+ _inherit = 'mail.template'
+
+ def ag_remove_powered_by_odoo(self):
+ powered_by = ""
+ for record in self:
+ if powered_by in str(record.body_html):
+ body_html = record.body_html
+ soup = BeautifulSoup(body_html, 'html.parser')
+ powered_element = soup.find('td', attrs={'style': 'text-align: center; font-size: 13px;'})
+
+ if powered_element:
+ powered_element['style'] = 'text-align: center; font-size: 13px; display: none !important;'
+ record.write({'body_html': str(soup)})
+ return {
+ 'type': 'ir.actions.client',
+ 'tag': 'display_notification',
+ 'params': {
+ 'type': 'success',
+ 'sticky': True,
+ 'message': _('Templates have been cleaned up successfully'),
+ 'next': {
+ 'type': 'ir.actions.client',
+ 'tag': 'reload'
+ }
+ }
+ }
+ else:
+ return {
+ 'type': 'ir.actions.client',
+ 'tag': 'display_notification',
+ 'sticky': True,
+ 'params': {
+ 'type': 'warning',
+ 'message': _('Powered by Odoo not found in the template'),
+ }
+ }
diff --git a/odex30_base/odex30_debrand/models/publisher_warranty_contract.py b/odex30_base/odex30_debrand/models/publisher_warranty_contract.py
new file mode 100644
index 0000000..8cc19ff
--- /dev/null
+++ b/odex30_base/odex30_debrand/models/publisher_warranty_contract.py
@@ -0,0 +1,13 @@
+# Copyright (C) 2013 Therp BV ().
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
+
+from odoo import models
+from odoo.release import version_info
+
+
+class PublisherWarrantyContract(models.AbstractModel):
+ _inherit = "publisher_warranty.contract"
+
+ def update_notification(self, cron_mode=True):
+ if version_info[5] == "e":
+ return super().update_notification(cron_mode=cron_mode)
diff --git a/odex30_base/odex30_debrand/models/res_config_settings.py b/odex30_base/odex30_debrand/models/res_config_settings.py
new file mode 100644
index 0000000..e374707
--- /dev/null
+++ b/odex30_base/odex30_debrand/models/res_config_settings.py
@@ -0,0 +1,52 @@
+# -*- coding: utf-8 -*-
+from odoo import api, fields, models, modules
+
+
+class ResConfigSettings(models.TransientModel):
+ _inherit = 'res.config.settings'
+
+ style = fields.Selection([('default', 'Default'), ('left', 'Left'), ('right', 'Right'), ('middle', 'Middle')], help='Select Background Theme')
+ background = fields.Selection([('image', 'Image'), ('color', 'Color')], default='color', help='Select Background Theme')
+ background_image = fields.Many2one('login.image', string="Image", help='Select Background Image For Login Page')
+ color = fields.Char(string="Color", help="Choose your Background color")
+
+ @api.onchange('background')
+ def onchange_background(self):
+ if self.background == 'image':
+ self.color = False
+ elif self.background == 'color':
+ self.background_image = False
+ else:
+ self.background_image = self.color = False
+
+ @api.onchange('style')
+ def onchange_style(self):
+ if self.style == 'default' or self.style is False:
+ self.background = self.background_image = self.color = False
+
+ @api.model
+ def get_values(self):
+ res = super(ResConfigSettings, self).get_values()
+ image_param = self.env['ir.config_parameter'].sudo().get_param('login_background.background_image')
+ image_record = self.env['login.image'].browse(int(image_param)) if image_param else False
+ res.update(
+ background_image=image_record,
+ color=self.env['ir.config_parameter'].sudo().get_param('login_background.color'),
+ background=self.env['ir.config_parameter'].sudo().get_param('login_background.background'),
+ style=self.env['ir.config_parameter'].sudo().get_param('login_background.style'),
+ )
+ return res
+
+ def set_values(self):
+ super(ResConfigSettings, self).set_values()
+ param = self.env['ir.config_parameter'].sudo()
+
+ set_image = self.background_image.id or False
+ set_color = self.color or False
+ set_background = self.background or False
+ set_style = self.style or False
+
+ param.set_param('login_background.background_image', set_image)
+ param.set_param('login_background.color', set_color)
+ param.set_param('login_background.background', set_background)
+ param.set_param('login_background.style', set_style)
diff --git a/odex30_base/odex30_debrand/security/ir.model.access.csv b/odex30_base/odex30_debrand/security/ir.model.access.csv
new file mode 100644
index 0000000..965046d
--- /dev/null
+++ b/odex30_base/odex30_debrand/security/ir.model.access.csv
@@ -0,0 +1,2 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+access_login_image,access_login_image,model_login_image,,1,1,1,1
diff --git a/odex30_base/odex30_debrand/static/img/favicon.ico b/odex30_base/odex30_debrand/static/img/favicon.ico
new file mode 100644
index 0000000..d847b5a
Binary files /dev/null and b/odex30_base/odex30_debrand/static/img/favicon.ico differ
diff --git a/odex30_base/odex30_debrand/static/img/favicon.ico.old.ico b/odex30_base/odex30_debrand/static/img/favicon.ico.old.ico
new file mode 100644
index 0000000..a17251d
Binary files /dev/null and b/odex30_base/odex30_debrand/static/img/favicon.ico.old.ico differ
diff --git a/odex30_base/odex30_debrand/static/src/css/web_login_style.css b/odex30_base/odex30_debrand/static/src/css/web_login_style.css
new file mode 100644
index 0000000..9592042
--- /dev/null
+++ b/odex30_base/odex30_debrand/static/src/css/web_login_style.css
@@ -0,0 +1,55 @@
+/* .container{
+ max-width: 100%;
+} */
+#background{
+ height:100%;
+ display: block;
+ background-repeat: no-repeat;
+ background-position: center center;
+ background-attachment: fixed;
+ -webkit-background-size: cover;
+ -moz-background-size: cover;
+ -o-background-size: cover;
+ background-size: cover;
+ -webkit-filter: blur(0px);
+ z-index: -1;
+}
+.body_login {
+ display: inline-block;
+ text-align: center;
+ white-space: nowrap;
+ width: 100%;
+ position: relative;
+ margin: 0px;
+ padding: 0px;
+ opacity:0.7;
+}
+#mcard{
+ margin-top: 7%;
+ padding: 3%;
+ max-width:350px
+}
+
+#bcard{
+ padding: 3%;
+ height: 100%;
+}
+
+.body_login input,
+.body_login select {
+ background-color: transparent !important;
+ border-top: 0px;
+ border-left: 0px;
+ border-right: 0px;
+ border-bottom: 1px solid #FED766;
+ border-radius: 0px;
+ color: black;
+ font-size: 18px;
+ font-weight: 300;
+ transition: border-color 0.7s ease;
+ box-shadow: none!important;
+ text-align: center;
+}
+.effect:hover{
+ box-shadow: 5px 5px 5px black;
+}
\ No newline at end of file
diff --git a/odex30_base/odex30_debrand/static/src/js/favicon.js b/odex30_base/odex30_debrand/static/src/js/favicon.js
new file mode 100644
index 0000000..e41538e
--- /dev/null
+++ b/odex30_base/odex30_debrand/static/src/js/favicon.js
@@ -0,0 +1,51 @@
+/** @odoo-module **/
+
+document.addEventListener('DOMContentLoaded', function() {
+
+ const originalTitle = document.title;
+
+ if (originalTitle.includes('Odoo')) {
+ document.title = originalTitle.replace(/Odoo/g, 'Odex');
+
+ }
+
+ const observer = new MutationObserver(function(mutations) {
+
+ mutations.forEach(function(mutation) {
+ if (mutation.type === 'childList') {
+ const newTitle = document.title;
+
+ if (newTitle.includes('Odoo')) {
+ const updatedTitle = newTitle.replace(/Odoo/g, 'Odex');
+ document.title = updatedTitle;
+
+ }
+ }
+ });
+ });
+
+ const titleElement = document.querySelector('title');
+ if (titleElement) {
+ observer.observe(titleElement, {
+ childList: true,
+ characterData: true,
+ subtree: true
+ });
+ }
+
+});
+
+let lastTitle = document.title;
+setInterval(function() {
+ if (document.title !== lastTitle) {
+
+
+ if (document.title.includes('Odoo')) {
+ const newTitle = document.title.replace(/Odoo/g, 'Odex');
+ document.title = newTitle;
+ }
+
+ lastTitle = document.title;
+ }
+}, 500);
+
diff --git a/odex30_base/odex30_debrand/static/src/xml/base.xml b/odex30_base/odex30_debrand/static/src/xml/base.xml
new file mode 100644
index 0000000..0910672
--- /dev/null
+++ b/odex30_base/odex30_debrand/static/src/xml/base.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+ this.remove();
+
+
+
diff --git a/odex30_base/odex30_debrand/templates/assets.xml b/odex30_base/odex30_debrand/templates/assets.xml
new file mode 100644
index 0000000..33001dd
--- /dev/null
+++ b/odex30_base/odex30_debrand/templates/assets.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/odex30_base/odex30_debrand/templates/left_login_template.xml b/odex30_base/odex30_debrand/templates/left_login_template.xml
new file mode 100644
index 0000000..51a24bd
--- /dev/null
+++ b/odex30_base/odex30_debrand/templates/left_login_template.xml
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/odex30_base/odex30_debrand/templates/middle_login_template.xml b/odex30_base/odex30_debrand/templates/middle_login_template.xml
new file mode 100644
index 0000000..9a59638
--- /dev/null
+++ b/odex30_base/odex30_debrand/templates/middle_login_template.xml
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/odex30_base/odex30_debrand/templates/right_login_template.xml b/odex30_base/odex30_debrand/templates/right_login_template.xml
new file mode 100644
index 0000000..b661143
--- /dev/null
+++ b/odex30_base/odex30_debrand/templates/right_login_template.xml
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/odex30_base/odex30_debrand/views/assets.xml b/odex30_base/odex30_debrand/views/assets.xml
new file mode 100644
index 0000000..8799b4f
--- /dev/null
+++ b/odex30_base/odex30_debrand/views/assets.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/odex30_base/odex30_debrand/views/ir_ui_menu.xml b/odex30_base/odex30_debrand/views/ir_ui_menu.xml
new file mode 100644
index 0000000..28e5e55
--- /dev/null
+++ b/odex30_base/odex30_debrand/views/ir_ui_menu.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+ App Store
+ apps
+
+
+
+
+ Updates
+ apps.updates
+ {}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/odex30_base/odex30_debrand/views/login_image.xml b/odex30_base/odex30_debrand/views/login_image.xml
new file mode 100644
index 0000000..3f014c4
--- /dev/null
+++ b/odex30_base/odex30_debrand/views/login_image.xml
@@ -0,0 +1,34 @@
+
+
+
+ login.image
+ login.image
+
+
+
+
+
+
+
+
+ login.image
+ login.image
+
+
+
+
+
+
+
+ Image
+ login.image
+ list,form
+
+
+
+
\ No newline at end of file
diff --git a/odex30_base/odex30_debrand/views/mail_template_remove_odoo_views.xml b/odex30_base/odex30_debrand/views/mail_template_remove_odoo_views.xml
new file mode 100644
index 0000000..3b7d3b3
--- /dev/null
+++ b/odex30_base/odex30_debrand/views/mail_template_remove_odoo_views.xml
@@ -0,0 +1,11 @@
+
+
+
+ Remove Powered By Odoo
+
+
+ list
+ code
+ action = records.ag_remove_powered_by_odoo()
+
+
diff --git a/odex30_base/odex30_debrand/views/portal_template.xml b/odex30_base/odex30_debrand/views/portal_template.xml
new file mode 100644
index 0000000..128c44a
--- /dev/null
+++ b/odex30_base/odex30_debrand/views/portal_template.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
diff --git a/odex30_base/odex30_debrand/views/res_config_settings_views.xml b/odex30_base/odex30_debrand/views/res_config_settings_views.xml
new file mode 100644
index 0000000..34393f3
--- /dev/null
+++ b/odex30_base/odex30_debrand/views/res_config_settings_views.xml
@@ -0,0 +1,45 @@
+
+
+
+
+ res.config.settings.form.inherit
+ res.config.settings
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/odex30_base/odex30_debrand/views/webclient_templates.xml b/odex30_base/odex30_debrand/views/webclient_templates.xml
new file mode 100644
index 0000000..a2a4a43
--- /dev/null
+++ b/odex30_base/odex30_debrand/views/webclient_templates.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/odex30_base/odex30_debrand/views/website_footer_brand_promotion.xml b/odex30_base/odex30_debrand/views/website_footer_brand_promotion.xml
new file mode 100644
index 0000000..dd23f3c
--- /dev/null
+++ b/odex30_base/odex30_debrand/views/website_footer_brand_promotion.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+ Powered by %s%s
+
+
+
+
+
diff --git a/odex30_base/odex30_web_map/__init__.py b/odex30_base/odex30_web_map/__init__.py
new file mode 100644
index 0000000..d8b1596
--- /dev/null
+++ b/odex30_base/odex30_web_map/__init__.py
@@ -0,0 +1,5 @@
+# -*- coding: utf-8 -*-
+
+
+from . import models
+from . import validation
diff --git a/odex30_base/odex30_web_map/__manifest__.py b/odex30_base/odex30_web_map/__manifest__.py
new file mode 100644
index 0000000..1f15f3d
--- /dev/null
+++ b/odex30_base/odex30_web_map/__manifest__.py
@@ -0,0 +1,37 @@
+# -*- coding: utf-8 -*-
+
+{
+ 'name':"Map View",
+ 'summary':"Defines the map view for odoo enterprise",
+ 'description':"Allows the viewing of records on a map",
+ 'category': 'Hidden',
+ 'author': 'Expert Co. Ltd.',
+ 'website': 'http://www.exp-sa.com',
+ 'version':'1.0',
+ 'depends':['web', 'base_setup'],
+ 'data':[
+ "views/assets.xml",
+ "views/res_config_settings.xml",
+ "views/res_partner_views.xml",
+ ],
+ 'qweb':[
+ "static/src/xml/map.xml"
+ ],
+ 'assets': {
+ 'web.assets_backend': [
+ 'odex30_web_map/static/src/js/map_controller.js',
+ 'odex30_web_map/static/src/js/map_model.js',
+ 'odex30_web_map/static/src/js/map_renderer.js',
+ 'odex30_web_map/static/src/js/map_view.js',
+ 'odex30_web_map/static/src/scss/map_view.scss',
+ 'odex30_web_map/static/lib/leaflet/leaflet.js',
+ 'odex30_web_map/static/lib/leaflet/leaflet.css',
+ ],
+ 'web.qunit_suite_tests': [
+ '/odex30_web_map/static/tests/map_view_tests.js'
+ ]
+ },
+
+ 'auto_install': True,
+
+}
diff --git a/odex30_base/odex30_web_map/i18n/ar.po b/odex30_base/odex30_web_map/i18n/ar.po
new file mode 100644
index 0000000..e4e2760
--- /dev/null
+++ b/odex30_base/odex30_web_map/i18n/ar.po
@@ -0,0 +1,302 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * odex30_web_map
+#
+# Translators:
+# Sherif Abd Ekmoniem , 2020
+# Mustafa Rawi , 2020
+# Akram Alfusayal , 2020
+# amrnegm , 2020
+# Martin Trigaux, 2020
+# Osama Ahmaro , 2020
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 14.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2020-11-27 13:48+0000\n"
+"PO-Revision-Date: 2020-09-07 08:25+0000\n"
+"Last-Translator: Osama Ahmaro , 2020\n"
+"Language-Team: Arabic (https://www.transifex.com/odoo/teams/41243/ar/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Language: ar\n"
+"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
+
+#. module: odex30_web_map
+#: model_terms:ir.ui.view,arch_db:odex30_web_map.res_config_settings_view_form
+msgid ""
+" \n"
+" Get token"
+msgstr ""
+
+#. module: odex30_web_map
+#: model_terms:ir.ui.view,arch_db:odex30_web_map.res_config_settings_view_form
+msgid "Map Routes "
+msgstr ""
+
+#. module: odex30_web_map
+#: model:ir.model,name:odex30_web_map.model_ir_actions_act_window_view
+msgid "Action Window View"
+msgstr "عرض نافذة الإجراء"
+
+#. module: odex30_web_map
+#. openerp-web
+#: code:addons/odex30_web_map/static/src/js/map_renderer.js:0
+#: code:addons/odex30_web_map/static/src/js/map_renderer.js:0
+#, python-format
+msgid "Address"
+msgstr "العنوان"
+
+#. module: odex30_web_map
+#: model:ir.model,name:odex30_web_map.model_base
+msgid "Base"
+msgstr "أساس"
+
+#. module: odex30_web_map
+#. openerp-web
+#: code:addons/odex30_web_map/static/src/xml/map.xml:0
+#: code:addons/odex30_web_map/static/src/xml/map.xml:0
+#, python-format
+msgid "Close"
+msgstr "اغلاق"
+
+#. module: odex30_web_map
+#: model:ir.model,name:odex30_web_map.model_res_config_settings
+msgid "Config Settings"
+msgstr "ضبط الاعدادات"
+
+#. module: odex30_web_map
+#: model:ir.model,name:odex30_web_map.model_res_partner
+msgid "Contact"
+msgstr "جهة الاتصال"
+
+#. module: odex30_web_map
+#: model:ir.model.fields,field_description:odex30_web_map.field_res_partner__contact_address_complete
+#: model:ir.model.fields,field_description:odex30_web_map.field_res_users__contact_address_complete
+msgid "Contact Address Complete"
+msgstr ""
+
+#. module: odex30_web_map
+#: model:ir.model.fields,field_description:odex30_web_map.field_ir_actions_act_window_view__display_name
+#: model:ir.model.fields,field_description:odex30_web_map.field_ir_http__display_name
+#: model:ir.model.fields,field_description:odex30_web_map.field_ir_ui_view__display_name
+#: model:ir.model.fields,field_description:odex30_web_map.field_res_config_settings__display_name
+#: model:ir.model.fields,field_description:odex30_web_map.field_res_partner__display_name
+msgid "Display Name"
+msgstr "الاسم المعروض"
+
+#. module: odex30_web_map
+#: model:ir.model,name:odex30_web_map.model_ir_http
+msgid "HTTP Routing"
+msgstr "مسار HTTP"
+
+#. module: odex30_web_map
+#: model:ir.model.fields,field_description:odex30_web_map.field_ir_actions_act_window_view__id
+#: model:ir.model.fields,field_description:odex30_web_map.field_ir_http__id
+#: model:ir.model.fields,field_description:odex30_web_map.field_ir_ui_view__id
+#: model:ir.model.fields,field_description:odex30_web_map.field_res_config_settings__id
+#: model:ir.model.fields,field_description:odex30_web_map.field_res_partner__id
+msgid "ID"
+msgstr "المُعرف"
+
+#. module: odex30_web_map
+#. openerp-web
+#: code:addons/odex30_web_map/static/src/js/map_view.js:0
+#, python-format
+msgid "Items"
+msgstr "العناصر"
+
+#. module: odex30_web_map
+#: model:ir.model.fields,field_description:odex30_web_map.field_ir_actions_act_window_view____last_update
+#: model:ir.model.fields,field_description:odex30_web_map.field_ir_http____last_update
+#: model:ir.model.fields,field_description:odex30_web_map.field_ir_ui_view____last_update
+#: model:ir.model.fields,field_description:odex30_web_map.field_res_config_settings____last_update
+#: model:ir.model.fields,field_description:odex30_web_map.field_res_partner____last_update
+msgid "Last Modified on"
+msgstr "آخر تعديل في"
+
+#. module: odex30_web_map
+#. openerp-web
+#: code:addons/odex30_web_map/static/src/xml/map.xml:0
+#, python-format
+msgid "Locating new addresses..."
+msgstr ""
+
+#. module: odex30_web_map
+#: model:ir.model.fields.selection,name:odex30_web_map.selection__ir_actions_act_window_view__view_mode__map
+#: model:ir.model.fields.selection,name:odex30_web_map.selection__ir_ui_view__type__map
+msgid "Map"
+msgstr ""
+
+#. module: odex30_web_map
+#. openerp-web
+#: code:addons/odex30_web_map/static/src/js/map_model.js:0
+#, python-format
+msgid "MapBox servers unreachable"
+msgstr ""
+
+#. module: odex30_web_map
+#. openerp-web
+#: code:addons/odex30_web_map/static/src/js/map_renderer.js:0
+#, python-format
+msgid "Name"
+msgstr "الاسم"
+
+#. module: odex30_web_map
+#: model:ir.model.fields,help:odex30_web_map.field_res_config_settings__map_box_token
+msgid "Necessary for some functionalities in the map view"
+msgstr ""
+
+#. module: odex30_web_map
+#: model_terms:ir.ui.view,arch_db:odex30_web_map.res_config_settings_view_form
+msgid "Set a MapBox account to activate routes and style"
+msgstr ""
+
+#. module: odex30_web_map
+#. openerp-web
+#: code:addons/odex30_web_map/static/src/xml/map.xml:0
+#, python-format
+msgid "Set up token"
+msgstr ""
+
+#. module: odex30_web_map
+#. openerp-web
+#: code:addons/odex30_web_map/static/src/js/map_model.js:0
+#, python-format
+msgid "Some routing points are too far apart"
+msgstr ""
+
+#. module: odex30_web_map
+#: code:addons/odex30_web_map/models/res_config_settings.py:0
+#, python-format
+msgid "The MapBox server is unreachable"
+msgstr ""
+
+#. module: odex30_web_map
+#: code:addons/odex30_web_map/models/res_config_settings.py:0
+#, python-format
+msgid "The token input is not valid"
+msgstr ""
+
+#. module: odex30_web_map
+#. openerp-web
+#: code:addons/odex30_web_map/static/src/js/map_model.js:0
+#: code:addons/odex30_web_map/static/src/js/map_model.js:0
+#: code:addons/odex30_web_map/static/src/js/map_model.js:0
+#, python-format
+msgid ""
+"The view has switched to another provider but functionalities will be "
+"limited"
+msgstr ""
+
+#. module: odex30_web_map
+#: code:addons/odex30_web_map/models/res_config_settings.py:0
+#, python-format
+msgid "This referer is not authorized"
+msgstr ""
+
+#. module: odex30_web_map
+#. openerp-web
+#: code:addons/odex30_web_map/static/src/xml/map.xml:0
+#, python-format
+msgid "To get routing on your map, you first need to setup your Mapbox token."
+msgstr ""
+
+#. module: odex30_web_map
+#: model_terms:ir.ui.view,arch_db:odex30_web_map.res_config_settings_view_form
+msgid "Token"
+msgstr "كلمة السر"
+
+#. module: odex30_web_map
+#: model:ir.model.fields,field_description:odex30_web_map.field_res_config_settings__map_box_token
+msgid "Token Map Box"
+msgstr ""
+
+#. module: odex30_web_map
+#. openerp-web
+#: code:addons/odex30_web_map/static/src/js/map_model.js:0
+#, python-format
+msgid "Token invalid"
+msgstr ""
+
+#. module: odex30_web_map
+#. openerp-web
+#: code:addons/odex30_web_map/static/src/js/map_model.js:0
+#, python-format
+msgid "Too many requests, try again in a few minutes"
+msgstr ""
+
+#. module: odex30_web_map
+#. openerp-web
+#: code:addons/odex30_web_map/static/src/js/map_model.js:0
+#, python-format
+msgid "Too many routing points (maximum 25)"
+msgstr ""
+
+#. module: odex30_web_map
+#. openerp-web
+#: code:addons/odex30_web_map/static/src/js/map_model.js:0
+#, python-format
+msgid "Unauthorized connection"
+msgstr ""
+
+#. module: odex30_web_map
+#. openerp-web
+#: code:addons/odex30_web_map/static/src/xml/map.xml:0
+#, python-format
+msgid "Undefined"
+msgstr "غير محدد"
+
+#. module: odex30_web_map
+#. openerp-web
+#: code:addons/odex30_web_map/static/src/xml/map.xml:0
+#, python-format
+msgid "Unsuccessful routing request:"
+msgstr ""
+
+#. module: odex30_web_map
+#. openerp-web
+#: code:addons/odex30_web_map/static/src/js/map_view.js:0
+#, python-format
+msgid "Untitled"
+msgstr "غير مسمى"
+
+#. module: odex30_web_map
+#: model:ir.model,name:odex30_web_map.model_ir_ui_view
+msgid "View"
+msgstr "أداة العرض"
+
+#. module: odex30_web_map
+#: model:ir.model.fields,field_description:odex30_web_map.field_ir_actions_act_window_view__view_mode
+#: model:ir.model.fields,field_description:odex30_web_map.field_ir_ui_view__type
+msgid "View Type"
+msgstr "نوع واجهة العرض"
+
+#. module: odex30_web_map
+#. openerp-web
+#: code:addons/odex30_web_map/static/src/xml/map.xml:0
+#, python-format
+msgid "View in Google Maps"
+msgstr ""
+
+#. module: odex30_web_map
+#: code:addons/odex30_web_map/models/models.py:0
+#, python-format
+msgid "You need to set a Contact field on this model to use the Map View"
+msgstr ""
+
+#. module: odex30_web_map
+#. openerp-web
+#: code:addons/odex30_web_map/static/src/xml/map.xml:0
+#, python-format
+msgid "navigate to"
+msgstr ""
+
+#. module: odex30_web_map
+#. openerp-web
+#: code:addons/odex30_web_map/static/src/xml/map.xml:0
+#, python-format
+msgid "open"
+msgstr ""
diff --git a/odex30_base/odex30_web_map/models/__init__.py b/odex30_base/odex30_web_map/models/__init__.py
new file mode 100644
index 0000000..46b95d5
--- /dev/null
+++ b/odex30_base/odex30_web_map/models/__init__.py
@@ -0,0 +1,9 @@
+# -*- coding: utf-8 -*-
+
+
+from . import ir_action
+from . import ir_ui_view
+from . import res_partner
+from . import res_config_settings
+from . import models
+from . import ir_http
diff --git a/odex30_base/odex30_web_map/models/ir_action.py b/odex30_base/odex30_web_map/models/ir_action.py
new file mode 100644
index 0000000..21ca0f8
--- /dev/null
+++ b/odex30_base/odex30_web_map/models/ir_action.py
@@ -0,0 +1,12 @@
+# -*- coding: utf-8 -*-
+
+
+from odoo import fields, models
+
+
+class ActWindowView(models.Model):
+ _inherit = 'ir.actions.act_window.view'
+
+ view_mode = fields.Selection(selection_add=[
+ ('map', "Map")
+ ], ondelete={'map': 'cascade'})
diff --git a/odex30_base/odex30_web_map/models/ir_http.py b/odex30_base/odex30_web_map/models/ir_http.py
new file mode 100644
index 0000000..60ebcb7
--- /dev/null
+++ b/odex30_base/odex30_web_map/models/ir_http.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+
+
+from odoo import models
+
+
+class IrHttp(models.AbstractModel):
+ _inherit = 'ir.http'
+
+ def session_info(self):
+ result = super(IrHttp, self).session_info()
+ if self.env.user.has_group('base.group_user'):
+ result.update(
+ map_box_token = self.env['ir.config_parameter'].sudo().get_param('odex30_web_map.token_map_box',False)
+ )
+ return result
diff --git a/odex30_base/odex30_web_map/models/ir_ui_view.py b/odex30_base/odex30_web_map/models/ir_ui_view.py
new file mode 100644
index 0000000..55ca2bf
--- /dev/null
+++ b/odex30_base/odex30_web_map/models/ir_ui_view.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+
+
+from odoo import fields, models
+
+
+class View(models.Model):
+ _inherit = 'ir.ui.view'
+
+ type = fields.Selection(selection_add=[('map', "Map")])
diff --git a/odex30_base/odex30_web_map/models/models.py b/odex30_base/odex30_web_map/models/models.py
new file mode 100644
index 0000000..9180d5a
--- /dev/null
+++ b/odex30_base/odex30_web_map/models/models.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+
+
+from odoo import _, api, models
+from lxml.builder import E
+from odoo.exceptions import UserError
+
+
+class Base(models.AbstractModel):
+ _inherit = 'base'
+
+ @api.model
+ def _get_default_map_view(self):
+ view = E.map()
+
+ if 'partner_id' in self._fields:
+ view.set('res_partner', 'partner_id')
+ else:
+ raise UserError(_("You need to set a Contact field on this model to use the Map View"))
+
+ return view
diff --git a/odex30_base/odex30_web_map/models/res_config_settings.py b/odex30_base/odex30_web_map/models/res_config_settings.py
new file mode 100644
index 0000000..1eb9e5f
--- /dev/null
+++ b/odex30_base/odex30_web_map/models/res_config_settings.py
@@ -0,0 +1,43 @@
+# -*- coding: utf-8 -*-
+
+
+from odoo import fields, models,api, _
+from odoo.exceptions import UserError
+import requests
+from odoo.http import request
+
+
+class ResConfigSettings(models.TransientModel):
+ _inherit = 'res.config.settings'
+
+ map_box_token = fields.Char(config_parameter='odex30_web_map.token_map_box',string = 'Token Map Box', help='Necessary for some functionalities in the map view', copy=True, default='', store=True)
+
+ def check_token_validity(self):
+ url = 'https://api.mapbox.com/directions/v5/mapbox/driving/-73.989%2C40.733%3B-74%2C40.733?access_token='+self.map_box_token+'&steps=true&geometries=geojson'
+ environ = request.httprequest.headers.environ
+ # if self.map_box_token != '':
+ # try:
+ # headers = {
+ # 'referer': environ.get('HTTP_REFERER')
+ # }
+ # result = requests.get(url=url, headers=headers)
+ # error_code = result.status_code
+ # if(result.status_code != 200):
+ # self.map_box_token = ''
+ # if error_code == 401:
+ # raise UserError(_('The token input is not valid'))
+ # elif error_code == 403:
+ # raise UserError(_('This referer is not authorized'))
+ # elif error_code == 500:
+ # raise UserError(_('The MapBox server is unreachable'))
+ # except Exception:
+ # raise
+
+ @api.model
+ def set_values(self):
+ # check validity of mapbox token only when it is being changed
+ if self.map_box_token:
+ map_box_token = self.env['ir.config_parameter'].get_param('odex30_web_map.token_map_box')
+ if map_box_token != self.map_box_token:
+ self.check_token_validity()
+ super(ResConfigSettings, self).set_values()
diff --git a/odex30_base/odex30_web_map/models/res_partner.py b/odex30_base/odex30_web_map/models/res_partner.py
new file mode 100644
index 0000000..3c469ac
--- /dev/null
+++ b/odex30_base/odex30_web_map/models/res_partner.py
@@ -0,0 +1,51 @@
+# -*- coding: utf-8 -*-
+
+
+from collections import defaultdict
+
+from odoo import api, fields, models
+
+
+class ResPartner(models.Model):
+ _name = 'res.partner'
+ _inherit = 'res.partner'
+
+ contact_address_complete = fields.Char(compute='_compute_complete_address', store=True)
+
+ @api.model
+ def update_latitude_longitude(self, partners):
+ partners_data = defaultdict(list)
+
+ for partner in partners:
+ if 'id' in partner and 'partner_latitude' in partner and 'partner_longitude' in partner:
+ partners_data[(partner['partner_latitude'], partner['partner_longitude'])].append(partner['id'])
+
+ for values, partner_ids in partners_data.items():
+ # NOTE this should be done in sudo to avoid crashing as soon as the view is used
+ self.browse(partner_ids).sudo().write({
+ 'partner_latitude': values[0],
+ 'partner_longitude': values[1],
+ })
+
+ return {}
+
+ @api.onchange('street', 'zip', 'city', 'state_id', 'country_id')
+ def _delete_coordinates(self):
+ self.partner_latitude = False
+ self.partner_longitude = False
+
+ @api.depends('street', 'zip', 'city', 'country_id')
+ def _compute_complete_address(self):
+ for record in self:
+ record.contact_address_complete = ''
+ if record.street:
+ record.contact_address_complete += record.street + ', '
+ if record.zip:
+ record.contact_address_complete += record.zip + ' '
+ if record.city:
+ record.contact_address_complete += record.city + ', '
+ if record.state_id:
+ record.contact_address_complete += record.state_id.name + ', '
+ if record.country_id:
+ record.contact_address_complete += record.country_id.name
+ record.contact_address_complete = record.contact_address_complete.strip().strip(',')
diff --git a/odex30_base/odex30_web_map/static/description/icon.png b/odex30_base/odex30_web_map/static/description/icon.png
new file mode 100644
index 0000000..4141f52
Binary files /dev/null and b/odex30_base/odex30_web_map/static/description/icon.png differ
diff --git a/odex30_base/odex30_web_map/static/img/pin-circle.svg b/odex30_base/odex30_web_map/static/img/pin-circle.svg
new file mode 100644
index 0000000..06d9981
--- /dev/null
+++ b/odex30_base/odex30_web_map/static/img/pin-circle.svg
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/odex30_base/odex30_web_map/static/img/pin-no-circle.svg b/odex30_base/odex30_web_map/static/img/pin-no-circle.svg
new file mode 100644
index 0000000..de48b2d
--- /dev/null
+++ b/odex30_base/odex30_web_map/static/img/pin-no-circle.svg
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/odex30_base/odex30_web_map/static/lib/leaflet/images/layers-2x.png b/odex30_base/odex30_web_map/static/lib/leaflet/images/layers-2x.png
new file mode 100644
index 0000000..200c333
Binary files /dev/null and b/odex30_base/odex30_web_map/static/lib/leaflet/images/layers-2x.png differ
diff --git a/odex30_base/odex30_web_map/static/lib/leaflet/images/layers.png b/odex30_base/odex30_web_map/static/lib/leaflet/images/layers.png
new file mode 100644
index 0000000..1a72e57
Binary files /dev/null and b/odex30_base/odex30_web_map/static/lib/leaflet/images/layers.png differ
diff --git a/odex30_base/odex30_web_map/static/lib/leaflet/images/marker-icon-2x.png b/odex30_base/odex30_web_map/static/lib/leaflet/images/marker-icon-2x.png
new file mode 100644
index 0000000..88f9e50
Binary files /dev/null and b/odex30_base/odex30_web_map/static/lib/leaflet/images/marker-icon-2x.png differ
diff --git a/odex30_base/odex30_web_map/static/lib/leaflet/images/marker-icon-numbered.png b/odex30_base/odex30_web_map/static/lib/leaflet/images/marker-icon-numbered.png
new file mode 100644
index 0000000..e02bbdf
Binary files /dev/null and b/odex30_base/odex30_web_map/static/lib/leaflet/images/marker-icon-numbered.png differ
diff --git a/odex30_base/odex30_web_map/static/lib/leaflet/images/marker-icon.png b/odex30_base/odex30_web_map/static/lib/leaflet/images/marker-icon.png
new file mode 100644
index 0000000..950edf2
Binary files /dev/null and b/odex30_base/odex30_web_map/static/lib/leaflet/images/marker-icon.png differ
diff --git a/odex30_base/odex30_web_map/static/lib/leaflet/images/marker-shadow.png b/odex30_base/odex30_web_map/static/lib/leaflet/images/marker-shadow.png
new file mode 100644
index 0000000..9fd2979
Binary files /dev/null and b/odex30_base/odex30_web_map/static/lib/leaflet/images/marker-shadow.png differ
diff --git a/odex30_base/odex30_web_map/static/lib/leaflet/leaflet.css b/odex30_base/odex30_web_map/static/lib/leaflet/leaflet.css
new file mode 100644
index 0000000..70802f3
--- /dev/null
+++ b/odex30_base/odex30_web_map/static/lib/leaflet/leaflet.css
@@ -0,0 +1,635 @@
+/* required styles */
+
+.leaflet-pane,
+.leaflet-tile,
+.leaflet-marker-icon,
+.leaflet-marker-shadow,
+.leaflet-tile-container,
+.leaflet-pane > svg,
+.leaflet-pane > canvas,
+.leaflet-zoom-box,
+.leaflet-image-layer,
+.leaflet-layer {
+ position: absolute;
+ left: 0;
+ top: 0;
+ }
+.leaflet-container {
+ overflow: hidden;
+ }
+.leaflet-tile,
+.leaflet-marker-icon,
+.leaflet-marker-shadow {
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ user-select: none;
+ -webkit-user-drag: none;
+ }
+/* Safari renders non-retina tile on retina better with this, but Chrome is worse */
+.leaflet-safari .leaflet-tile {
+ image-rendering: -webkit-optimize-contrast;
+ }
+/* hack that prevents hw layers "stretching" when loading new tiles */
+.leaflet-safari .leaflet-tile-container {
+ width: 1600px;
+ height: 1600px;
+ -webkit-transform-origin: 0 0;
+ }
+.leaflet-marker-icon,
+.leaflet-marker-shadow {
+ display: block;
+ }
+/* .leaflet-container svg: reset svg max-width decleration shipped in Joomla! (joomla.org) 3.x */
+/* .leaflet-container img: map is broken in FF if you have max-width: 100% on tiles */
+.leaflet-container .leaflet-overlay-pane svg,
+.leaflet-container .leaflet-marker-pane img,
+.leaflet-container .leaflet-shadow-pane img,
+.leaflet-container .leaflet-tile-pane img,
+.leaflet-container img.leaflet-image-layer,
+.leaflet-container .leaflet-tile {
+ max-width: none !important;
+ max-height: none !important;
+ }
+
+.leaflet-container.leaflet-touch-zoom {
+ -ms-touch-action: pan-x pan-y;
+ touch-action: pan-x pan-y;
+ }
+.leaflet-container.leaflet-touch-drag {
+ -ms-touch-action: pinch-zoom;
+ /* Fallback for FF which doesn't support pinch-zoom */
+ touch-action: none;
+ touch-action: pinch-zoom;
+}
+.leaflet-container.leaflet-touch-drag.leaflet-touch-zoom {
+ -ms-touch-action: none;
+ touch-action: none;
+}
+.leaflet-container {
+ -webkit-tap-highlight-color: transparent;
+}
+.leaflet-container a {
+ -webkit-tap-highlight-color: rgba(51, 181, 229, 0.4);
+}
+.leaflet-tile {
+ filter: inherit;
+ visibility: hidden;
+ }
+.leaflet-tile-loaded {
+ visibility: inherit;
+ }
+.leaflet-zoom-box {
+ width: 0;
+ height: 0;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ z-index: 800;
+ }
+/* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */
+.leaflet-overlay-pane svg {
+ -moz-user-select: none;
+ }
+
+.leaflet-pane { z-index: 400; }
+
+.leaflet-tile-pane { z-index: 200; }
+.leaflet-overlay-pane { z-index: 400; }
+.leaflet-shadow-pane { z-index: 500; }
+.leaflet-marker-pane { z-index: 600; }
+.leaflet-tooltip-pane { z-index: 650; }
+.leaflet-popup-pane { z-index: 700; }
+
+.leaflet-map-pane canvas { z-index: 100; }
+.leaflet-map-pane svg { z-index: 200; }
+
+.leaflet-vml-shape {
+ width: 1px;
+ height: 1px;
+ }
+.lvml {
+ behavior: url(#default#VML);
+ display: inline-block;
+ position: absolute;
+ }
+
+
+/* control positioning */
+
+.leaflet-control {
+ position: relative;
+ z-index: 800;
+ pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */
+ pointer-events: auto;
+ }
+.leaflet-top,
+.leaflet-bottom {
+ position: absolute;
+ z-index: 1000;
+ pointer-events: none;
+ }
+.leaflet-top {
+ top: 0;
+ }
+.leaflet-right {
+ right: 0;
+ }
+.leaflet-bottom {
+ bottom: 0;
+ }
+.leaflet-left {
+ left: 0;
+ }
+.leaflet-control {
+ float: left;
+ clear: both;
+ }
+.leaflet-right .leaflet-control {
+ float: right;
+ }
+.leaflet-top .leaflet-control {
+ margin-top: 10px;
+ }
+.leaflet-bottom .leaflet-control {
+ margin-bottom: 10px;
+ }
+.leaflet-left .leaflet-control {
+ margin-left: 10px;
+ }
+.leaflet-right .leaflet-control {
+ margin-right: 10px;
+ }
+
+
+/* zoom and fade animations */
+
+.leaflet-fade-anim .leaflet-tile {
+ will-change: opacity;
+ }
+.leaflet-fade-anim .leaflet-popup {
+ opacity: 0;
+ -webkit-transition: opacity 0.2s linear;
+ -moz-transition: opacity 0.2s linear;
+ transition: opacity 0.2s linear;
+ }
+.leaflet-fade-anim .leaflet-map-pane .leaflet-popup {
+ opacity: 1;
+ }
+.leaflet-zoom-animated {
+ -webkit-transform-origin: 0 0;
+ -ms-transform-origin: 0 0;
+ transform-origin: 0 0;
+ }
+.leaflet-zoom-anim .leaflet-zoom-animated {
+ will-change: transform;
+ }
+.leaflet-zoom-anim .leaflet-zoom-animated {
+ -webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1);
+ -moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1);
+ transition: transform 0.25s cubic-bezier(0,0,0.25,1);
+ }
+.leaflet-zoom-anim .leaflet-tile,
+.leaflet-pan-anim .leaflet-tile {
+ -webkit-transition: none;
+ -moz-transition: none;
+ transition: none;
+ }
+
+.leaflet-zoom-anim .leaflet-zoom-hide {
+ visibility: hidden;
+ }
+
+
+/* cursors */
+
+.leaflet-interactive {
+ cursor: pointer;
+ }
+.leaflet-grab {
+ cursor: -webkit-grab;
+ cursor: -moz-grab;
+ cursor: grab;
+ }
+.leaflet-crosshair,
+.leaflet-crosshair .leaflet-interactive {
+ cursor: crosshair;
+ }
+.leaflet-popup-pane,
+.leaflet-control {
+ cursor: auto;
+ }
+.leaflet-dragging .leaflet-grab,
+.leaflet-dragging .leaflet-grab .leaflet-interactive,
+.leaflet-dragging .leaflet-marker-draggable {
+ cursor: move;
+ cursor: -webkit-grabbing;
+ cursor: -moz-grabbing;
+ cursor: grabbing;
+ }
+
+/* marker & overlays interactivity */
+.leaflet-marker-icon,
+.leaflet-marker-shadow,
+.leaflet-image-layer,
+.leaflet-pane > svg path,
+.leaflet-tile-container {
+ pointer-events: none;
+ }
+
+.leaflet-marker-icon.leaflet-interactive,
+.leaflet-image-layer.leaflet-interactive,
+.leaflet-pane > svg path.leaflet-interactive {
+ pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */
+ pointer-events: auto;
+ }
+
+/* visual tweaks */
+
+.leaflet-container {
+ background: #ddd;
+ outline: 0;
+ }
+.leaflet-container a {
+ color: #0078A8;
+ }
+.leaflet-container a.leaflet-active {
+ outline: 2px solid orange;
+ }
+.leaflet-zoom-box {
+ border: 2px dotted #38f;
+ background: rgba(255,255,255,0.5);
+ }
+
+
+/* general typography */
+.leaflet-container {
+ font: 12px/1.5 "Helvetica Neue", Arial, Helvetica, sans-serif;
+ }
+
+
+/* general toolbar styles */
+
+.leaflet-bar {
+ box-shadow: 0 1px 5px rgba(0,0,0,0.65);
+ border-radius: 4px;
+ }
+.leaflet-bar a,
+.leaflet-bar a:hover {
+ background-color: #fff;
+ border-bottom: 1px solid #ccc;
+ width: 26px;
+ height: 26px;
+ line-height: 26px;
+ display: block;
+ text-align: center;
+ text-decoration: none;
+ color: black;
+ }
+.leaflet-bar a,
+.leaflet-control-layers-toggle {
+ background-position: 50% 50%;
+ background-repeat: no-repeat;
+ display: block;
+ }
+.leaflet-bar a:hover {
+ background-color: #f4f4f4;
+ }
+.leaflet-bar a:first-child {
+ border-top-left-radius: 4px;
+ border-top-right-radius: 4px;
+ }
+.leaflet-bar a:last-child {
+ border-bottom-left-radius: 4px;
+ border-bottom-right-radius: 4px;
+ border-bottom: none;
+ }
+.leaflet-bar a.leaflet-disabled {
+ cursor: default;
+ background-color: #f4f4f4;
+ color: #bbb;
+ }
+
+.leaflet-touch .leaflet-bar a {
+ width: 30px;
+ height: 30px;
+ line-height: 30px;
+ }
+.leaflet-touch .leaflet-bar a:first-child {
+ border-top-left-radius: 2px;
+ border-top-right-radius: 2px;
+ }
+.leaflet-touch .leaflet-bar a:last-child {
+ border-bottom-left-radius: 2px;
+ border-bottom-right-radius: 2px;
+ }
+
+/* zoom control */
+
+.leaflet-control-zoom-in,
+.leaflet-control-zoom-out {
+ font: bold 18px 'Lucida Console', Monaco, monospace;
+ text-indent: 1px;
+ }
+
+.leaflet-touch .leaflet-control-zoom-in, .leaflet-touch .leaflet-control-zoom-out {
+ font-size: 22px;
+ }
+
+
+/* layers control */
+
+.leaflet-control-layers {
+ box-shadow: 0 1px 5px rgba(0,0,0,0.4);
+ background: #fff;
+ border-radius: 5px;
+ }
+.leaflet-control-layers-toggle {
+ background-image: url(images/layers.png);
+ width: 36px;
+ height: 36px;
+ }
+.leaflet-retina .leaflet-control-layers-toggle {
+ background-image: url(images/layers-2x.png);
+ background-size: 26px 26px;
+ }
+.leaflet-touch .leaflet-control-layers-toggle {
+ width: 44px;
+ height: 44px;
+ }
+.leaflet-control-layers .leaflet-control-layers-list,
+.leaflet-control-layers-expanded .leaflet-control-layers-toggle {
+ display: none;
+ }
+.leaflet-control-layers-expanded .leaflet-control-layers-list {
+ display: block;
+ position: relative;
+ }
+.leaflet-control-layers-expanded {
+ padding: 6px 10px 6px 6px;
+ color: #333;
+ background: #fff;
+ }
+.leaflet-control-layers-scrollbar {
+ overflow-y: scroll;
+ overflow-x: hidden;
+ padding-right: 5px;
+ }
+.leaflet-control-layers-selector {
+ margin-top: 2px;
+ position: relative;
+ top: 1px;
+ }
+.leaflet-control-layers label {
+ display: block;
+ }
+.leaflet-control-layers-separator {
+ height: 0;
+ border-top: 1px solid #ddd;
+ margin: 5px -10px 5px -6px;
+ }
+
+/* Default icon URLs */
+.leaflet-default-icon-path {
+ background-image: url(images/marker-icon.png);
+ }
+
+
+/* attribution and scale controls */
+
+.leaflet-container .leaflet-control-attribution {
+ background: #fff;
+ background: rgba(255, 255, 255, 0.7);
+ margin: 0;
+ }
+.leaflet-control-attribution,
+.leaflet-control-scale-line {
+ padding: 0 5px;
+ color: #333;
+ }
+.leaflet-control-attribution a {
+ text-decoration: none;
+ }
+.leaflet-control-attribution a:hover {
+ text-decoration: underline;
+ }
+.leaflet-container .leaflet-control-attribution,
+.leaflet-container .leaflet-control-scale {
+ font-size: 11px;
+ }
+.leaflet-left .leaflet-control-scale {
+ margin-left: 5px;
+ }
+.leaflet-bottom .leaflet-control-scale {
+ margin-bottom: 5px;
+ }
+.leaflet-control-scale-line {
+ border: 2px solid #777;
+ border-top: none;
+ line-height: 1.1;
+ padding: 2px 5px 1px;
+ font-size: 11px;
+ white-space: nowrap;
+ overflow: hidden;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+
+ background: #fff;
+ background: rgba(255, 255, 255, 0.5);
+ }
+.leaflet-control-scale-line:not(:first-child) {
+ border-top: 2px solid #777;
+ border-bottom: none;
+ margin-top: -2px;
+ }
+.leaflet-control-scale-line:not(:first-child):not(:last-child) {
+ border-bottom: 2px solid #777;
+ }
+
+.leaflet-touch .leaflet-control-attribution,
+.leaflet-touch .leaflet-control-layers,
+.leaflet-touch .leaflet-bar {
+ box-shadow: none;
+ }
+.leaflet-touch .leaflet-control-layers,
+.leaflet-touch .leaflet-bar {
+ border: 2px solid rgba(0,0,0,0.2);
+ background-clip: padding-box;
+ }
+
+
+/* popup */
+
+.leaflet-popup {
+ position: absolute;
+ text-align: center;
+ margin-bottom: 20px;
+ }
+.leaflet-popup-content-wrapper {
+ padding: 1px;
+ text-align: left;
+ border-radius: 12px;
+ }
+.leaflet-popup-content {
+ margin: 13px 19px;
+ line-height: 1.4;
+ }
+.leaflet-popup-content p {
+ margin: 18px 0;
+ }
+.leaflet-popup-tip-container {
+ width: 40px;
+ height: 20px;
+ position: absolute;
+ left: 50%;
+ margin-left: -20px;
+ overflow: hidden;
+ pointer-events: none;
+ }
+.leaflet-popup-tip {
+ width: 17px;
+ height: 17px;
+ padding: 1px;
+
+ margin: -10px auto 0;
+
+ -webkit-transform: rotate(45deg);
+ -moz-transform: rotate(45deg);
+ -ms-transform: rotate(45deg);
+ transform: rotate(45deg);
+ }
+.leaflet-popup-content-wrapper,
+.leaflet-popup-tip {
+ background: white;
+ color: #333;
+ box-shadow: 0 3px 14px rgba(0,0,0,0.4);
+ }
+.leaflet-container a.leaflet-popup-close-button {
+ position: absolute;
+ top: 0;
+ right: 0;
+ padding: 4px 4px 0 0;
+ border: none;
+ text-align: center;
+ width: 18px;
+ height: 14px;
+ font: 16px/14px Tahoma, Verdana, sans-serif;
+ color: #c3c3c3;
+ text-decoration: none;
+ font-weight: bold;
+ background: transparent;
+ }
+.leaflet-container a.leaflet-popup-close-button:hover {
+ color: #999;
+ }
+.leaflet-popup-scrolled {
+ overflow: auto;
+ border-bottom: 1px solid #ddd;
+ border-top: 1px solid #ddd;
+ }
+
+.leaflet-oldie .leaflet-popup-content-wrapper {
+ zoom: 1;
+ }
+.leaflet-oldie .leaflet-popup-tip {
+ width: 24px;
+ margin: 0 auto;
+
+ -ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)";
+ filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678);
+ }
+.leaflet-oldie .leaflet-popup-tip-container {
+ margin-top: -1px;
+ }
+
+.leaflet-oldie .leaflet-control-zoom,
+.leaflet-oldie .leaflet-control-layers,
+.leaflet-oldie .leaflet-popup-content-wrapper,
+.leaflet-oldie .leaflet-popup-tip {
+ border: 1px solid #999;
+ }
+
+
+/* div icon */
+
+.leaflet-div-icon {
+ background: #fff;
+ border: 1px solid #666;
+ }
+
+
+/* Tooltip */
+/* Base styles for the element that has a tooltip */
+.leaflet-tooltip {
+ position: absolute;
+ padding: 6px;
+ background-color: #fff;
+ border: 1px solid #fff;
+ border-radius: 3px;
+ color: #222;
+ white-space: nowrap;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ pointer-events: none;
+ box-shadow: 0 1px 3px rgba(0,0,0,0.4);
+ }
+.leaflet-tooltip.leaflet-clickable {
+ cursor: pointer;
+ pointer-events: auto;
+ }
+.leaflet-tooltip-top:before,
+.leaflet-tooltip-bottom:before,
+.leaflet-tooltip-left:before,
+.leaflet-tooltip-right:before {
+ position: absolute;
+ pointer-events: none;
+ border: 6px solid transparent;
+ background: transparent;
+ content: "";
+ }
+
+/* Directions */
+
+.leaflet-tooltip-bottom {
+ margin-top: 6px;
+}
+.leaflet-tooltip-top {
+ margin-top: -6px;
+}
+.leaflet-tooltip-bottom:before,
+.leaflet-tooltip-top:before {
+ left: 50%;
+ margin-left: -6px;
+ }
+.leaflet-tooltip-top:before {
+ bottom: 0;
+ margin-bottom: -12px;
+ border-top-color: #fff;
+ }
+.leaflet-tooltip-bottom:before {
+ top: 0;
+ margin-top: -12px;
+ margin-left: -6px;
+ border-bottom-color: #fff;
+ }
+.leaflet-tooltip-left {
+ margin-left: -6px;
+}
+.leaflet-tooltip-right {
+ margin-left: 6px;
+}
+.leaflet-tooltip-left:before,
+.leaflet-tooltip-right:before {
+ top: 50%;
+ margin-top: -6px;
+ }
+.leaflet-tooltip-left:before {
+ right: 0;
+ margin-right: -12px;
+ border-left-color: #fff;
+ }
+.leaflet-tooltip-right:before {
+ left: 0;
+ margin-left: -12px;
+ border-right-color: #fff;
+ }
diff --git a/odex30_base/odex30_web_map/static/lib/leaflet/leaflet.js b/odex30_base/odex30_web_map/static/lib/leaflet/leaflet.js
new file mode 100644
index 0000000..576a90e
--- /dev/null
+++ b/odex30_base/odex30_web_map/static/lib/leaflet/leaflet.js
@@ -0,0 +1,5 @@
+/* @preserve
+ * Leaflet 1.4.0+Detached: 3337f36d2a2d2b33946779057619b31f674ff5dc.3337f36, a JS library for interactive maps. http://leafletjs.com
+ * (c) 2010-2018 Vladimir Agafonkin, (c) 2010-2011 CloudMade
+ */
+!function(t,i){"object"==typeof exports&&"undefined"!=typeof module?i(exports):"function"==typeof define&&define.amd?define(["exports"],i):i(t.L={})}(this,function(t){"use strict";function i(t){var i,e,n,o;for(e=1,n=arguments.length;e=0}function A(t,i,e,n){return"touchstart"===i?O(t,e,n):"touchmove"===i?W(t,e,n):"touchend"===i&&H(t,e,n),this}function I(t,i,e){var n=t["_leaflet_"+i+e];return"touchstart"===i?t.removeEventListener(te,n,!1):"touchmove"===i?t.removeEventListener(ie,n,!1):"touchend"===i&&(t.removeEventListener(ee,n,!1),t.removeEventListener(ne,n,!1)),this}function O(t,i,n){var o=e(function(t){if("mouse"!==t.pointerType&&t.MSPOINTER_TYPE_MOUSE&&t.pointerType!==t.MSPOINTER_TYPE_MOUSE){if(!(oe.indexOf(t.target.tagName)<0))return;Pt(t)}j(t,i)});t["_leaflet_touchstart"+n]=o,t.addEventListener(te,o,!1),re||(document.documentElement.addEventListener(te,R,!0),document.documentElement.addEventListener(ie,N,!0),document.documentElement.addEventListener(ee,D,!0),document.documentElement.addEventListener(ne,D,!0),re=!0)}function R(t){se[t.pointerId]=t,ae++}function N(t){se[t.pointerId]&&(se[t.pointerId]=t)}function D(t){delete se[t.pointerId],ae--}function j(t,i){t.touches=[];for(var e in se)t.touches.push(se[e]);t.changedTouches=[t],i(t)}function W(t,i,e){var n=function(t){(t.pointerType!==t.MSPOINTER_TYPE_MOUSE&&"mouse"!==t.pointerType||0!==t.buttons)&&j(t,i)};t["_leaflet_touchmove"+e]=n,t.addEventListener(ie,n,!1)}function H(t,i,e){var n=function(t){j(t,i)};t["_leaflet_touchend"+e]=n,t.addEventListener(ee,n,!1),t.addEventListener(ne,n,!1)}function F(t,i,e){function n(t){var i;if(Vi){if(!bi||"mouse"===t.pointerType)return;i=ae}else i=t.touches.length;if(!(i>1)){var e=Date.now(),n=e-(s||e);r=t.touches?t.touches[0]:t,a=n>0&&n<=h,s=e}}function o(t){if(a&&!r.cancelBubble){if(Vi){if(!bi||"mouse"===t.pointerType)return;var e,n,o={};for(n in r)e=r[n],o[n]=e&&e.bind?e.bind(r):e;r=o}r.type="dblclick",i(r),s=null}}var s,r,a=!1,h=250;return t[le+he+e]=n,t[le+ue+e]=o,t[le+"dblclick"+e]=i,t.addEventListener(he,n,!1),t.addEventListener(ue,o,!1),t.addEventListener("dblclick",i,!1),this}function U(t,i){var e=t[le+he+i],n=t[le+ue+i],o=t[le+"dblclick"+i];return t.removeEventListener(he,e,!1),t.removeEventListener(ue,n,!1),bi||t.removeEventListener("dblclick",o,!1),this}function V(t){return"string"==typeof t?document.getElementById(t):t}function q(t,i){var e=t.style[i]||t.currentStyle&&t.currentStyle[i];if((!e||"auto"===e)&&document.defaultView){var n=document.defaultView.getComputedStyle(t,null);e=n?n[i]:null}return"auto"===e?null:e}function G(t,i,e){var n=document.createElement(t);return n.className=i||"",e&&e.appendChild(n),n}function K(t){var i=t.parentNode;i&&i.removeChild(t)}function Y(t){for(;t.firstChild;)t.removeChild(t.firstChild)}function X(t){var i=t.parentNode;i&&i.lastChild!==t&&i.appendChild(t)}function J(t){var i=t.parentNode;i&&i.firstChild!==t&&i.insertBefore(t,i.firstChild)}function $(t,i){if(void 0!==t.classList)return t.classList.contains(i);var e=et(t);return e.length>0&&new RegExp("(^|\\s)"+i+"(\\s|$)").test(e)}function Q(t,i){if(void 0!==t.classList)for(var e=u(i),n=0,o=e.length;n100&&n<500||t.target._simulatedClick&&!t._simulated?Lt(t):(ge=e,i(t))}function Zt(t,i){if(!i||!t.length)return t.slice();var e=i*i;return t=At(t,e),t=kt(t,e)}function Et(t,i,e){return Math.sqrt(Dt(t,i,e,!0))}function kt(t,i){var e=t.length,n=new(typeof Uint8Array!=void 0+""?Uint8Array:Array)(e);n[0]=n[e-1]=1,Bt(t,n,i,0,e-1);var o,s=[];for(o=0;oh&&(s=r,h=a);h>e&&(i[s]=1,Bt(t,i,e,n,s),Bt(t,i,e,s,o))}function At(t,i){for(var e=[t[0]],n=1,o=0,s=t.length;ni&&(e.push(t[n]),o=n);return oi.max.x&&(e|=2),t.yi.max.y&&(e|=8),e}function Nt(t,i){var e=i.x-t.x,n=i.y-t.y;return e*e+n*n}function Dt(t,i,e,n){var o,s=i.x,r=i.y,a=e.x-s,h=e.y-r,u=a*a+h*h;return u>0&&((o=((t.x-s)*a+(t.y-r)*h)/u)>1?(s=e.x,r=e.y):o>0&&(s+=a*o,r+=h*o)),a=t.x-s,h=t.y-r,n?a*a+h*h:new x(s,r)}function jt(t){return!oi(t[0])||"object"!=typeof t[0][0]&&void 0!==t[0][0]}function Wt(t){return console.warn("Deprecated use of _flat, please use L.LineUtil.isFlat instead."),jt(t)}function Ht(t,i,e){var n,o,s,r,a,h,u,l,c,_=[1,4,2,8];for(o=0,u=t.length;o0?Math.floor(t):Math.ceil(t)};x.prototype={clone:function(){return new x(this.x,this.y)},add:function(t){return this.clone()._add(w(t))},_add:function(t){return this.x+=t.x,this.y+=t.y,this},subtract:function(t){return this.clone()._subtract(w(t))},_subtract:function(t){return this.x-=t.x,this.y-=t.y,this},divideBy:function(t){return this.clone()._divideBy(t)},_divideBy:function(t){return this.x/=t,this.y/=t,this},multiplyBy:function(t){return this.clone()._multiplyBy(t)},_multiplyBy:function(t){return this.x*=t,this.y*=t,this},scaleBy:function(t){return new x(this.x*t.x,this.y*t.y)},unscaleBy:function(t){return new x(this.x/t.x,this.y/t.y)},round:function(){return this.clone()._round()},_round:function(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this},floor:function(){return this.clone()._floor()},_floor:function(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this},ceil:function(){return this.clone()._ceil()},_ceil:function(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this},trunc:function(){return this.clone()._trunc()},_trunc:function(){return this.x=_i(this.x),this.y=_i(this.y),this},distanceTo:function(t){var i=(t=w(t)).x-this.x,e=t.y-this.y;return Math.sqrt(i*i+e*e)},equals:function(t){return(t=w(t)).x===this.x&&t.y===this.y},contains:function(t){return t=w(t),Math.abs(t.x)<=Math.abs(this.x)&&Math.abs(t.y)<=Math.abs(this.y)},toString:function(){return"Point("+a(this.x)+", "+a(this.y)+")"}},P.prototype={extend:function(t){return t=w(t),this.min||this.max?(this.min.x=Math.min(t.x,this.min.x),this.max.x=Math.max(t.x,this.max.x),this.min.y=Math.min(t.y,this.min.y),this.max.y=Math.max(t.y,this.max.y)):(this.min=t.clone(),this.max=t.clone()),this},getCenter:function(t){return new x((this.min.x+this.max.x)/2,(this.min.y+this.max.y)/2,t)},getBottomLeft:function(){return new x(this.min.x,this.max.y)},getTopRight:function(){return new x(this.max.x,this.min.y)},getTopLeft:function(){return this.min},getBottomRight:function(){return this.max},getSize:function(){return this.max.subtract(this.min)},contains:function(t){var i,e;return(t="number"==typeof t[0]||t instanceof x?w(t):b(t))instanceof P?(i=t.min,e=t.max):i=e=t,i.x>=this.min.x&&e.x<=this.max.x&&i.y>=this.min.y&&e.y<=this.max.y},intersects:function(t){t=b(t);var i=this.min,e=this.max,n=t.min,o=t.max,s=o.x>=i.x&&n.x<=e.x,r=o.y>=i.y&&n.y<=e.y;return s&&r},overlaps:function(t){t=b(t);var i=this.min,e=this.max,n=t.min,o=t.max,s=o.x>i.x&&n.xi.y&&n.y=n.lat&&e.lat<=o.lat&&i.lng>=n.lng&&e.lng<=o.lng},intersects:function(t){t=z(t);var i=this._southWest,e=this._northEast,n=t.getSouthWest(),o=t.getNorthEast(),s=o.lat>=i.lat&&n.lat<=e.lat,r=o.lng>=i.lng&&n.lng<=e.lng;return s&&r},overlaps:function(t){t=z(t);var i=this._southWest,e=this._northEast,n=t.getSouthWest(),o=t.getNorthEast(),s=o.lat>i.lat&&n.lati.lng&&n.lng1,Xi=!!document.createElement("canvas").getContext,Ji=!(!document.createElementNS||!E("svg").createSVGRect),$i=!Ji&&function(){try{var t=document.createElement("div");t.innerHTML=' ';var i=t.firstChild;return i.style.behavior="url(#default#VML)",i&&"object"==typeof i.adj}catch(t){return!1}}(),Qi=(Object.freeze||Object)({ie:Pi,ielt9:Li,edge:bi,webkit:Ti,android:zi,android23:Mi,androidStock:Si,opera:Zi,chrome:Ei,gecko:ki,safari:Bi,phantom:Ai,opera12:Ii,win:Oi,ie3d:Ri,webkit3d:Ni,gecko3d:Di,any3d:ji,mobile:Wi,mobileWebkit:Hi,mobileWebkit3d:Fi,msPointer:Ui,pointer:Vi,touch:qi,mobileOpera:Gi,mobileGecko:Ki,retina:Yi,canvas:Xi,svg:Ji,vml:$i}),te=Ui?"MSPointerDown":"pointerdown",ie=Ui?"MSPointerMove":"pointermove",ee=Ui?"MSPointerUp":"pointerup",ne=Ui?"MSPointerCancel":"pointercancel",oe=["INPUT","SELECT","OPTION"],se={},re=!1,ae=0,he=Ui?"MSPointerDown":Vi?"pointerdown":"touchstart",ue=Ui?"MSPointerUp":Vi?"pointerup":"touchend",le="_leaflet_",ce=st(["transform","webkitTransform","OTransform","MozTransform","msTransform"]),_e=st(["webkitTransition","transition","OTransition","MozTransition","msTransition"]),de="webkitTransition"===_e||"OTransition"===_e?_e+"End":"transitionend";if("onselectstart"in document)fi=function(){mt(window,"selectstart",Pt)},gi=function(){ft(window,"selectstart",Pt)};else{var pe=st(["userSelect","WebkitUserSelect","OUserSelect","MozUserSelect","msUserSelect"]);fi=function(){if(pe){var t=document.documentElement.style;vi=t[pe],t[pe]="none"}},gi=function(){pe&&(document.documentElement.style[pe]=vi,vi=void 0)}}var me,fe,ge,ve=(Object.freeze||Object)({TRANSFORM:ce,TRANSITION:_e,TRANSITION_END:de,get:V,getStyle:q,create:G,remove:K,empty:Y,toFront:X,toBack:J,hasClass:$,addClass:Q,removeClass:tt,setClass:it,getClass:et,setOpacity:nt,testProp:st,setTransform:rt,setPosition:at,getPosition:ht,disableTextSelection:fi,enableTextSelection:gi,disableImageDrag:ut,enableImageDrag:lt,preventOutline:ct,restoreOutline:_t,getSizedParentNode:dt,getScale:pt}),ye="_leaflet_events",xe=Oi&&Ei?2*window.devicePixelRatio:ki?window.devicePixelRatio:1,we={},Pe=(Object.freeze||Object)({on:mt,off:ft,stopPropagation:yt,disableScrollPropagation:xt,disableClickPropagation:wt,preventDefault:Pt,stop:Lt,getMousePosition:bt,getWheelDelta:Tt,fakeStop:zt,skipped:Mt,isExternalTarget:Ct,addListener:mt,removeListener:ft}),Le=ci.extend({run:function(t,i,e,n){this.stop(),this._el=t,this._inProgress=!0,this._duration=e||.25,this._easeOutPower=1/Math.max(n||.5,.2),this._startPos=ht(t),this._offset=i.subtract(this._startPos),this._startTime=+new Date,this.fire("start"),this._animate()},stop:function(){this._inProgress&&(this._step(!0),this._complete())},_animate:function(){this._animId=f(this._animate,this),this._step()},_step:function(t){var i=+new Date-this._startTime,e=1e3*this._duration;ithis.options.maxZoom)?this.setZoom(t):this},panInsideBounds:function(t,i){this._enforcingBounds=!0;var e=this.getCenter(),n=this._limitCenter(e,this._zoom,z(t));return e.equals(n)||this.panTo(n,i),this._enforcingBounds=!1,this},panInside:function(t,i){var e=w((i=i||{}).paddingTopLeft||i.padding||[0,0]),n=w(i.paddingBottomRight||i.padding||[0,0]),o=this.getCenter(),s=this.project(o),r=this.project(t),a=this.getPixelBounds(),h=a.getSize().divideBy(2),u=b([a.min.add(e),a.max.subtract(n)]);if(!u.contains(r)){this._enforcingBounds=!0;var l=s.subtract(r),c=w(r.x+l.x,r.y+l.y);(r.xu.max.x)&&(c.x=s.x-l.x,l.x>0?c.x+=h.x-e.x:c.x-=h.x-n.x),(r.yu.max.y)&&(c.y=s.y-l.y,l.y>0?c.y+=h.y-e.y:c.y-=h.y-n.y),this.panTo(this.unproject(c),i),this._enforcingBounds=!1}return this},invalidateSize:function(t){if(!this._loaded)return this;t=i({animate:!1,pan:!0},!0===t?{animate:!0}:t);var n=this.getSize();this._sizeChanged=!0,this._lastCenter=null;var o=this.getSize(),s=n.divideBy(2).round(),r=o.divideBy(2).round(),a=s.subtract(r);return a.x||a.y?(t.animate&&t.pan?this.panBy(a):(t.pan&&this._rawPanBy(a),this.fire("move"),t.debounceMoveend?(clearTimeout(this._sizeTimer),this._sizeTimer=setTimeout(e(this.fire,this,"moveend"),200)):this.fire("moveend")),this.fire("resize",{oldSize:n,newSize:o})):this},stop:function(){return this.setZoom(this._limitZoom(this._zoom)),this.options.zoomSnap||this.fire("viewreset"),this._stop()},locate:function(t){if(t=this._locateOptions=i({timeout:1e4,watch:!1},t),!("geolocation"in navigator))return this._handleGeolocationError({code:0,message:"Geolocation not supported."}),this;var n=e(this._handleGeolocationResponse,this),o=e(this._handleGeolocationError,this);return t.watch?this._locationWatchId=navigator.geolocation.watchPosition(n,o,t):navigator.geolocation.getCurrentPosition(n,o,t),this},stopLocate:function(){return navigator.geolocation&&navigator.geolocation.clearWatch&&navigator.geolocation.clearWatch(this._locationWatchId),this._locateOptions&&(this._locateOptions.setView=!1),this},_handleGeolocationError:function(t){var i=t.code,e=t.message||(1===i?"permission denied":2===i?"position unavailable":"timeout");this._locateOptions.setView&&!this._loaded&&this.fitWorld(),this.fire("locationerror",{code:i,message:"Geolocation error: "+e+"."})},_handleGeolocationResponse:function(t){var i=new M(t.coords.latitude,t.coords.longitude),e=i.toBounds(2*t.coords.accuracy),n=this._locateOptions;if(n.setView){var o=this.getBoundsZoom(e);this.setView(i,n.maxZoom?Math.min(o,n.maxZoom):o)}var s={latlng:i,bounds:e,timestamp:t.timestamp};for(var r in t.coords)"number"==typeof t.coords[r]&&(s[r]=t.coords[r]);this.fire("locationfound",s)},addHandler:function(t,i){if(!i)return this;var e=this[t]=new i(this);return this._handlers.push(e),this.options[t]&&e.enable(),this},remove:function(){if(this._initEvents(!0),this._containerId!==this._container._leaflet_id)throw new Error("Map container is being reused by another instance");try{delete this._container._leaflet_id,delete this._containerId}catch(t){this._container._leaflet_id=void 0,this._containerId=void 0}void 0!==this._locationWatchId&&this.stopLocate(),this._stop(),K(this._mapPane),this._clearControlPos&&this._clearControlPos(),this._resizeRequest&&(g(this._resizeRequest),this._resizeRequest=null),this._clearHandlers(),this._loaded&&this.fire("unload");var t;for(t in this._layers)this._layers[t].remove();for(t in this._panes)K(this._panes[t]);return this._layers=[],this._panes=[],delete this._mapPane,delete this._renderer,this},createPane:function(t,i){var e=G("div","leaflet-pane"+(t?" leaflet-"+t.replace("Pane","")+"-pane":""),i||this._mapPane);return t&&(this._panes[t]=e),e},getCenter:function(){return this._checkIfLoaded(),this._lastCenter&&!this._moved()?this._lastCenter:this.layerPointToLatLng(this._getCenterLayerPoint())},getZoom:function(){return this._zoom},getBounds:function(){var t=this.getPixelBounds();return new T(this.unproject(t.getBottomLeft()),this.unproject(t.getTopRight()))},getMinZoom:function(){return void 0===this.options.minZoom?this._layersMinZoom||0:this.options.minZoom},getMaxZoom:function(){return void 0===this.options.maxZoom?void 0===this._layersMaxZoom?1/0:this._layersMaxZoom:this.options.maxZoom},getBoundsZoom:function(t,i,e){t=z(t),e=w(e||[0,0]);var n=this.getZoom()||0,o=this.getMinZoom(),s=this.getMaxZoom(),r=t.getNorthWest(),a=t.getSouthEast(),h=this.getSize().subtract(e),u=b(this.project(a,n),this.project(r,n)).getSize(),l=ji?this.options.zoomSnap:1,c=h.x/u.x,_=h.y/u.y,d=i?Math.max(c,_):Math.min(c,_);return n=this.getScaleZoom(d,n),l&&(n=Math.round(n/(l/100))*(l/100),n=i?Math.ceil(n/l)*l:Math.floor(n/l)*l),Math.max(o,Math.min(s,n))},getSize:function(){return this._size&&!this._sizeChanged||(this._size=new x(this._container.clientWidth||0,this._container.clientHeight||0),this._sizeChanged=!1),this._size.clone()},getPixelBounds:function(t,i){var e=this._getTopLeftPoint(t,i);return new P(e,e.add(this.getSize()))},getPixelOrigin:function(){return this._checkIfLoaded(),this._pixelOrigin},getPixelWorldBounds:function(t){return this.options.crs.getProjectedBounds(void 0===t?this.getZoom():t)},getPane:function(t){return"string"==typeof t?this._panes[t]:t},getPanes:function(){return this._panes},getContainer:function(){return this._container},getZoomScale:function(t,i){var e=this.options.crs;return i=void 0===i?this._zoom:i,e.scale(t)/e.scale(i)},getScaleZoom:function(t,i){var e=this.options.crs;i=void 0===i?this._zoom:i;var n=e.zoom(t*e.scale(i));return isNaN(n)?1/0:n},project:function(t,i){return i=void 0===i?this._zoom:i,this.options.crs.latLngToPoint(C(t),i)},unproject:function(t,i){return i=void 0===i?this._zoom:i,this.options.crs.pointToLatLng(w(t),i)},layerPointToLatLng:function(t){var i=w(t).add(this.getPixelOrigin());return this.unproject(i)},latLngToLayerPoint:function(t){return this.project(C(t))._round()._subtract(this.getPixelOrigin())},wrapLatLng:function(t){return this.options.crs.wrapLatLng(C(t))},wrapLatLngBounds:function(t){return this.options.crs.wrapLatLngBounds(z(t))},distance:function(t,i){return this.options.crs.distance(C(t),C(i))},containerPointToLayerPoint:function(t){return w(t).subtract(this._getMapPanePos())},layerPointToContainerPoint:function(t){return w(t).add(this._getMapPanePos())},containerPointToLatLng:function(t){var i=this.containerPointToLayerPoint(w(t));return this.layerPointToLatLng(i)},latLngToContainerPoint:function(t){return this.layerPointToContainerPoint(this.latLngToLayerPoint(C(t)))},mouseEventToContainerPoint:function(t){return bt(t,this._container)},mouseEventToLayerPoint:function(t){return this.containerPointToLayerPoint(this.mouseEventToContainerPoint(t))},mouseEventToLatLng:function(t){return this.layerPointToLatLng(this.mouseEventToLayerPoint(t))},_initContainer:function(t){var i=this._container=V(t);if(!i)throw new Error("Map container not found.");if(i._leaflet_id)throw new Error("Map container is already initialized.");mt(i,"scroll",this._onScroll,this),this._containerId=n(i)},_initLayout:function(){var t=this._container;this._fadeAnimated=this.options.fadeAnimation&&ji,Q(t,"leaflet-container"+(qi?" leaflet-touch":"")+(Yi?" leaflet-retina":"")+(Li?" leaflet-oldie":"")+(Bi?" leaflet-safari":"")+(this._fadeAnimated?" leaflet-fade-anim":""));var i=q(t,"position");"absolute"!==i&&"relative"!==i&&"fixed"!==i&&(t.style.position="relative"),this._initPanes(),this._initControlPos&&this._initControlPos()},_initPanes:function(){var t=this._panes={};this._paneRenderers={},this._mapPane=this.createPane("mapPane",this._container),at(this._mapPane,new x(0,0)),this.createPane("tilePane"),this.createPane("shadowPane"),this.createPane("overlayPane"),this.createPane("markerPane"),this.createPane("tooltipPane"),this.createPane("popupPane"),this.options.markerZoomAnimation||(Q(t.markerPane,"leaflet-zoom-hide"),Q(t.shadowPane,"leaflet-zoom-hide"))},_resetView:function(t,i){at(this._mapPane,new x(0,0));var e=!this._loaded;this._loaded=!0,i=this._limitZoom(i),this.fire("viewprereset");var n=this._zoom!==i;this._moveStart(n,!1)._move(t,i)._moveEnd(n),this.fire("viewreset"),e&&this.fire("load")},_moveStart:function(t,i){return t&&this.fire("zoomstart"),i||this.fire("movestart"),this},_move:function(t,i,e){void 0===i&&(i=this._zoom);var n=this._zoom!==i;return this._zoom=i,this._lastCenter=t,this._pixelOrigin=this._getNewPixelOrigin(t),(n||e&&e.pinch)&&this.fire("zoom",e),this.fire("move",e)},_moveEnd:function(t){return t&&this.fire("zoomend"),this.fire("moveend")},_stop:function(){return g(this._flyToFrame),this._panAnim&&this._panAnim.stop(),this},_rawPanBy:function(t){at(this._mapPane,this._getMapPanePos().subtract(t))},_getZoomSpan:function(){return this.getMaxZoom()-this.getMinZoom()},_panInsideMaxBounds:function(){this._enforcingBounds||this.panInsideBounds(this.options.maxBounds)},_checkIfLoaded:function(){if(!this._loaded)throw new Error("Set map center and zoom first.")},_initEvents:function(t){this._targets={},this._targets[n(this._container)]=this;var i=t?ft:mt;i(this._container,"click dblclick mousedown mouseup mouseover mouseout mousemove contextmenu keypress",this._handleDOMEvent,this),this.options.trackResize&&i(window,"resize",this._onResize,this),ji&&this.options.transform3DLimit&&(t?this.off:this.on).call(this,"moveend",this._onMoveEnd)},_onResize:function(){g(this._resizeRequest),this._resizeRequest=f(function(){this.invalidateSize({debounceMoveend:!0})},this)},_onScroll:function(){this._container.scrollTop=0,this._container.scrollLeft=0},_onMoveEnd:function(){var t=this._getMapPanePos();Math.max(Math.abs(t.x),Math.abs(t.y))>=this.options.transform3DLimit&&this._resetView(this.getCenter(),this.getZoom())},_findEventTargets:function(t,i){for(var e,o=[],s="mouseout"===i||"mouseover"===i,r=t.target||t.srcElement,a=!1;r;){if((e=this._targets[n(r)])&&("click"===i||"preclick"===i)&&!t._simulated&&this._draggableMoved(e)){a=!0;break}if(e&&e.listens(i,!0)){if(s&&!Ct(r,t))break;if(o.push(e),s)break}if(r===this._container)break;r=r.parentNode}return o.length||a||s||!Ct(r,t)||(o=[this]),o},_handleDOMEvent:function(t){if(this._loaded&&!Mt(t)){var i=t.type;"mousedown"!==i&&"keypress"!==i||ct(t.target||t.srcElement),this._fireDOMEvent(t,i)}},_mouseEvents:["click","dblclick","mouseover","mouseout","contextmenu"],_fireDOMEvent:function(t,e,n){if("click"===t.type){var o=i({},t);o.type="preclick",this._fireDOMEvent(o,o.type,n)}if(!t._stopped&&(n=(n||[]).concat(this._findEventTargets(t,e))).length){var s=n[0];"contextmenu"===e&&s.listens(e,!0)&&Pt(t);var r={originalEvent:t};if("keypress"!==t.type){var a=s.getLatLng&&(!s._radius||s._radius<=10);r.containerPoint=a?this.latLngToContainerPoint(s.getLatLng()):this.mouseEventToContainerPoint(t),r.layerPoint=this.containerPointToLayerPoint(r.containerPoint),r.latlng=a?s.getLatLng():this.layerPointToLatLng(r.layerPoint)}for(var h=0;h0?Math.round(t-i)/2:Math.max(0,Math.ceil(t))-Math.max(0,Math.floor(i))},_limitZoom:function(t){var i=this.getMinZoom(),e=this.getMaxZoom(),n=ji?this.options.zoomSnap:1;return n&&(t=Math.round(t/n)*n),Math.max(i,Math.min(e,t))},_onPanTransitionStep:function(){this.fire("move")},_onPanTransitionEnd:function(){tt(this._mapPane,"leaflet-pan-anim"),this.fire("moveend")},_tryAnimatedPan:function(t,i){var e=this._getCenterOffset(t)._trunc();return!(!0!==(i&&i.animate)&&!this.getSize().contains(e))&&(this.panBy(e,i),!0)},_createAnimProxy:function(){var t=this._proxy=G("div","leaflet-proxy leaflet-zoom-animated");this._panes.mapPane.appendChild(t),this.on("zoomanim",function(t){var i=ce,e=this._proxy.style[i];rt(this._proxy,this.project(t.center,t.zoom),this.getZoomScale(t.zoom,1)),e===this._proxy.style[i]&&this._animatingZoom&&this._onZoomTransitionEnd()},this),this.on("load moveend",function(){var t=this.getCenter(),i=this.getZoom();rt(this._proxy,this.project(t,i),this.getZoomScale(i,1))},this),this._on("unload",this._destroyAnimProxy,this)},_destroyAnimProxy:function(){K(this._proxy),delete this._proxy},_catchTransitionEnd:function(t){this._animatingZoom&&t.propertyName.indexOf("transform")>=0&&this._onZoomTransitionEnd()},_nothingToAnimate:function(){return!this._container.getElementsByClassName("leaflet-zoom-animated").length},_tryAnimatedZoom:function(t,i,e){if(this._animatingZoom)return!0;if(e=e||{},!this._zoomAnimated||!1===e.animate||this._nothingToAnimate()||Math.abs(i-this._zoom)>this.options.zoomAnimationThreshold)return!1;var n=this.getZoomScale(i),o=this._getCenterOffset(t)._divideBy(1-1/n);return!(!0!==e.animate&&!this.getSize().contains(o))&&(f(function(){this._moveStart(!0,!1)._animateZoom(t,i,!0)},this),!0)},_animateZoom:function(t,i,n,o){this._mapPane&&(n&&(this._animatingZoom=!0,this._animateToCenter=t,this._animateToZoom=i,Q(this._mapPane,"leaflet-zoom-anim")),this.fire("zoomanim",{center:t,zoom:i,noUpdate:o}),setTimeout(e(this._onZoomTransitionEnd,this),250))},_onZoomTransitionEnd:function(){this._animatingZoom&&(this._mapPane&&tt(this._mapPane,"leaflet-zoom-anim"),this._animatingZoom=!1,this._move(this._animateToCenter,this._animateToZoom),f(function(){this._moveEnd(!0)},this))}}),Te=v.extend({options:{position:"topright"},initialize:function(t){l(this,t)},getPosition:function(){return this.options.position},setPosition:function(t){var i=this._map;return i&&i.removeControl(this),this.options.position=t,i&&i.addControl(this),this},getContainer:function(){return this._container},addTo:function(t){this.remove(),this._map=t;var i=this._container=this.onAdd(t),e=this.getPosition(),n=t._controlCorners[e];return Q(i,"leaflet-control"),-1!==e.indexOf("bottom")?n.insertBefore(i,n.firstChild):n.appendChild(i),this},remove:function(){return this._map?(K(this._container),this.onRemove&&this.onRemove(this._map),this._map=null,this):this},_refocusOnMap:function(t){this._map&&t&&t.screenX>0&&t.screenY>0&&this._map.getContainer().focus()}}),ze=function(t){return new Te(t)};be.include({addControl:function(t){return t.addTo(this),this},removeControl:function(t){return t.remove(),this},_initControlPos:function(){function t(t,o){var s=e+t+" "+e+o;i[t+o]=G("div",s,n)}var i=this._controlCorners={},e="leaflet-",n=this._controlContainer=G("div",e+"control-container",this._container);t("top","left"),t("top","right"),t("bottom","left"),t("bottom","right")},_clearControlPos:function(){for(var t in this._controlCorners)K(this._controlCorners[t]);K(this._controlContainer),delete this._controlCorners,delete this._controlContainer}});var Me=Te.extend({options:{collapsed:!0,position:"topright",autoZIndex:!0,hideSingleBase:!1,sortLayers:!1,sortFunction:function(t,i,e,n){return e1,this._baseLayersList.style.display=t?"":"none"),this._separator.style.display=i&&t?"":"none",this},_onLayerChange:function(t){this._handlingClick||this._update();var i=this._getLayer(n(t.target)),e=i.overlay?"add"===t.type?"overlayadd":"overlayremove":"add"===t.type?"baselayerchange":null;e&&this._map.fire(e,i)},_createRadioElement:function(t,i){var e=' ",n=document.createElement("div");return n.innerHTML=e,n.firstChild},_addItem:function(t){var i,e=document.createElement("label"),o=this._map.hasLayer(t.layer);t.overlay?((i=document.createElement("input")).type="checkbox",i.className="leaflet-control-layers-selector",i.defaultChecked=o):i=this._createRadioElement("leaflet-base-layers",o),this._layerControlInputs.push(i),i.layerId=n(t.layer),mt(i,"click",this._onInputClick,this);var s=document.createElement("span");s.innerHTML=" "+t.name;var r=document.createElement("div");return e.appendChild(r),r.appendChild(i),r.appendChild(s),(t.overlay?this._overlaysList:this._baseLayersList).appendChild(e),this._checkDisabledLayers(),e},_onInputClick:function(){var t,i,e=this._layerControlInputs,n=[],o=[];this._handlingClick=!0;for(var s=e.length-1;s>=0;s--)t=e[s],i=this._getLayer(t.layerId).layer,t.checked?n.push(i):t.checked||o.push(i);for(s=0;s=0;o--)t=e[o],i=this._getLayer(t.layerId).layer,t.disabled=void 0!==i.options.minZoom&&ni.options.maxZoom},_expandIfNotCollapsed:function(){return this._map&&!this.options.collapsed&&this.expand(),this},_expand:function(){return this.expand()},_collapse:function(){return this.collapse()}}),Ce=Te.extend({options:{position:"topleft",zoomInText:"+",zoomInTitle:"Zoom in",zoomOutText:"−",zoomOutTitle:"Zoom out"},onAdd:function(t){var i="leaflet-control-zoom",e=G("div",i+" leaflet-bar"),n=this.options;return this._zoomInButton=this._createButton(n.zoomInText,n.zoomInTitle,i+"-in",e,this._zoomIn),this._zoomOutButton=this._createButton(n.zoomOutText,n.zoomOutTitle,i+"-out",e,this._zoomOut),this._updateDisabled(),t.on("zoomend zoomlevelschange",this._updateDisabled,this),e},onRemove:function(t){t.off("zoomend zoomlevelschange",this._updateDisabled,this)},disable:function(){return this._disabled=!0,this._updateDisabled(),this},enable:function(){return this._disabled=!1,this._updateDisabled(),this},_zoomIn:function(t){!this._disabled&&this._map._zoomthis._map.getMinZoom()&&this._map.zoomOut(this._map.options.zoomDelta*(t.shiftKey?3:1))},_createButton:function(t,i,e,n,o){var s=G("a",e,n);return s.innerHTML=t,s.href="#",s.title=i,s.setAttribute("role","button"),s.setAttribute("aria-label",i),wt(s),mt(s,"click",Lt),mt(s,"click",o,this),mt(s,"click",this._refocusOnMap,this),s},_updateDisabled:function(){var t=this._map,i="leaflet-disabled";tt(this._zoomInButton,i),tt(this._zoomOutButton,i),(this._disabled||t._zoom===t.getMinZoom())&&Q(this._zoomOutButton,i),(this._disabled||t._zoom===t.getMaxZoom())&&Q(this._zoomInButton,i)}});be.mergeOptions({zoomControl:!0}),be.addInitHook(function(){this.options.zoomControl&&(this.zoomControl=new Ce,this.addControl(this.zoomControl))});var Se=Te.extend({options:{position:"bottomleft",maxWidth:100,metric:!0,imperial:!0},onAdd:function(t){var i=G("div","leaflet-control-scale"),e=this.options;return this._addScales(e,"leaflet-control-scale-line",i),t.on(e.updateWhenIdle?"moveend":"move",this._update,this),t.whenReady(this._update,this),i},onRemove:function(t){t.off(this.options.updateWhenIdle?"moveend":"move",this._update,this)},_addScales:function(t,i,e){t.metric&&(this._mScale=G("div",i,e)),t.imperial&&(this._iScale=G("div",i,e))},_update:function(){var t=this._map,i=t.getSize().y/2,e=t.distance(t.containerPointToLatLng([0,i]),t.containerPointToLatLng([this.options.maxWidth,i]));this._updateScales(e)},_updateScales:function(t){this.options.metric&&t&&this._updateMetric(t),this.options.imperial&&t&&this._updateImperial(t)},_updateMetric:function(t){var i=this._getRoundNum(t),e=i<1e3?i+" m":i/1e3+" km";this._updateScale(this._mScale,e,i/t)},_updateImperial:function(t){var i,e,n,o=3.2808399*t;o>5280?(i=o/5280,e=this._getRoundNum(i),this._updateScale(this._iScale,e+" mi",e/i)):(n=this._getRoundNum(o),this._updateScale(this._iScale,n+" ft",n/o))},_updateScale:function(t,i,e){t.style.width=Math.round(this.options.maxWidth*e)+"px",t.innerHTML=i},_getRoundNum:function(t){var i=Math.pow(10,(Math.floor(t)+"").length-1),e=t/i;return e=e>=10?10:e>=5?5:e>=3?3:e>=2?2:1,i*e}}),Ze=Te.extend({options:{position:"bottomright",prefix:'Leaflet '},initialize:function(t){l(this,t),this._attributions={}},onAdd:function(t){t.attributionControl=this,this._container=G("div","leaflet-control-attribution"),wt(this._container);for(var i in t._layers)t._layers[i].getAttribution&&this.addAttribution(t._layers[i].getAttribution());return this._update(),this._container},setPrefix:function(t){return this.options.prefix=t,this._update(),this},addAttribution:function(t){return t?(this._attributions[t]||(this._attributions[t]=0),this._attributions[t]++,this._update(),this):this},removeAttribution:function(t){return t?(this._attributions[t]&&(this._attributions[t]--,this._update()),this):this},_update:function(){if(this._map){var t=[];for(var i in this._attributions)this._attributions[i]&&t.push(i);var e=[];this.options.prefix&&e.push(this.options.prefix),t.length&&e.push(t.join(", ")),this._container.innerHTML=e.join(" | ")}}});be.mergeOptions({attributionControl:!0}),be.addInitHook(function(){this.options.attributionControl&&(new Ze).addTo(this)});Te.Layers=Me,Te.Zoom=Ce,Te.Scale=Se,Te.Attribution=Ze,ze.layers=function(t,i,e){return new Me(t,i,e)},ze.zoom=function(t){return new Ce(t)},ze.scale=function(t){return new Se(t)},ze.attribution=function(t){return new Ze(t)};var Ee=v.extend({initialize:function(t){this._map=t},enable:function(){return this._enabled?this:(this._enabled=!0,this.addHooks(),this)},disable:function(){return this._enabled?(this._enabled=!1,this.removeHooks(),this):this},enabled:function(){return!!this._enabled}});Ee.addTo=function(t,i){return t.addHandler(i,this),this};var ke,Be={Events:li},Ae=qi?"touchstart mousedown":"mousedown",Ie={mousedown:"mouseup",touchstart:"touchend",pointerdown:"touchend",MSPointerDown:"touchend"},Oe={mousedown:"mousemove",touchstart:"touchmove",pointerdown:"touchmove",MSPointerDown:"touchmove"},Re=ci.extend({options:{clickTolerance:3},initialize:function(t,i,e,n){l(this,n),this._element=t,this._dragStartTarget=i||t,this._preventOutline=e},enable:function(){this._enabled||(mt(this._dragStartTarget,Ae,this._onDown,this),this._enabled=!0)},disable:function(){this._enabled&&(Re._dragging===this&&this.finishDrag(),ft(this._dragStartTarget,Ae,this._onDown,this),this._enabled=!1,this._moved=!1)},_onDown:function(t){if(!t._simulated&&this._enabled&&(this._moved=!1,!$(this._element,"leaflet-zoom-anim")&&!(Re._dragging||t.shiftKey||1!==t.which&&1!==t.button&&!t.touches||(Re._dragging=this,this._preventOutline&&ct(this._element),ut(),fi(),this._moving)))){this.fire("down");var i=t.touches?t.touches[0]:t,e=dt(this._element);this._startPoint=new x(i.clientX,i.clientY),this._parentScale=pt(e),mt(document,Oe[t.type],this._onMove,this),mt(document,Ie[t.type],this._onUp,this)}},_onMove:function(t){if(!t._simulated&&this._enabled)if(t.touches&&t.touches.length>1)this._moved=!0;else{var i=t.touches&&1===t.touches.length?t.touches[0]:t,e=new x(i.clientX,i.clientY)._subtract(this._startPoint);(e.x||e.y)&&(Math.abs(e.x)+Math.abs(e.y)1e-7;h++)i=s*Math.sin(a),i=Math.pow((1-i)/(1+i),s/2),a+=u=Math.PI/2-2*Math.atan(r*i)-a;return new M(a*e,t.x*e/n)}},He=(Object.freeze||Object)({LonLat:je,Mercator:We,SphericalMercator:mi}),Fe=i({},pi,{code:"EPSG:3395",projection:We,transformation:function(){var t=.5/(Math.PI*We.R);return Z(t,.5,-t,.5)}()}),Ue=i({},pi,{code:"EPSG:4326",projection:je,transformation:Z(1/180,1,-1/180,.5)}),Ve=i({},di,{projection:je,transformation:Z(1,0,-1,0),scale:function(t){return Math.pow(2,t)},zoom:function(t){return Math.log(t)/Math.LN2},distance:function(t,i){var e=i.lng-t.lng,n=i.lat-t.lat;return Math.sqrt(e*e+n*n)},infinite:!0});di.Earth=pi,di.EPSG3395=Fe,di.EPSG3857=yi,di.EPSG900913=xi,di.EPSG4326=Ue,di.Simple=Ve;var qe=ci.extend({options:{pane:"overlayPane",attribution:null,bubblingMouseEvents:!0},addTo:function(t){return t.addLayer(this),this},remove:function(){return this.removeFrom(this._map||this._mapToAdd)},removeFrom:function(t){return t&&t.removeLayer(this),this},getPane:function(t){return this._map.getPane(t?this.options[t]||t:this.options.pane)},addInteractiveTarget:function(t){return this._map._targets[n(t)]=this,this},removeInteractiveTarget:function(t){return delete this._map._targets[n(t)],this},getAttribution:function(){return this.options.attribution},_layerAdd:function(t){var i=t.target;if(i.hasLayer(this)){if(this._map=i,this._zoomAnimated=i._zoomAnimated,this.getEvents){var e=this.getEvents();i.on(e,this),this.once("remove",function(){i.off(e,this)},this)}this.onAdd(i),this.getAttribution&&i.attributionControl&&i.attributionControl.addAttribution(this.getAttribution()),this.fire("add"),i.fire("layeradd",{layer:this})}}});be.include({addLayer:function(t){if(!t._layerAdd)throw new Error("The provided object is not a Layer.");var i=n(t);return this._layers[i]?this:(this._layers[i]=t,t._mapToAdd=this,t.beforeAdd&&t.beforeAdd(this),this.whenReady(t._layerAdd,t),this)},removeLayer:function(t){var i=n(t);return this._layers[i]?(this._loaded&&t.onRemove(this),t.getAttribution&&this.attributionControl&&this.attributionControl.removeAttribution(t.getAttribution()),delete this._layers[i],this._loaded&&(this.fire("layerremove",{layer:t}),t.fire("remove")),t._map=t._mapToAdd=null,this):this},hasLayer:function(t){return!!t&&n(t)in this._layers},eachLayer:function(t,i){for(var e in this._layers)t.call(i,this._layers[e]);return this},_addLayers:function(t){for(var i=0,e=(t=t?oi(t)?t:[t]:[]).length;ithis._layersMaxZoom&&this.setZoom(this._layersMaxZoom),void 0===this.options.minZoom&&this._layersMinZoom&&this.getZoom()i)return r=(n-i)/e,this._map.layerPointToLatLng([s.x-r*(s.x-o.x),s.y-r*(s.y-o.y)])},getBounds:function(){return this._bounds},addLatLng:function(t,i){return i=i||this._defaultShape(),t=C(t),i.push(t),this._bounds.extend(t),this.redraw()},_setLatLngs:function(t){this._bounds=new T,this._latlngs=this._convertLatLngs(t)},_defaultShape:function(){return jt(this._latlngs)?this._latlngs:this._latlngs[0]},_convertLatLngs:function(t){for(var i=[],e=jt(t),n=0,o=t.length;n=2&&i[0]instanceof M&&i[0].equals(i[e-1])&&i.pop(),i},_setLatLngs:function(t){nn.prototype._setLatLngs.call(this,t),jt(this._latlngs)&&(this._latlngs=[this._latlngs])},_defaultShape:function(){return jt(this._latlngs[0])?this._latlngs[0]:this._latlngs[0][0]},_clipPoints:function(){var t=this._renderer._bounds,i=this.options.weight,e=new x(i,i);if(t=new P(t.min.subtract(e),t.max.add(e)),this._parts=[],this._pxBounds&&this._pxBounds.intersects(t))if(this.options.noClip)this._parts=this._rings;else for(var n,o=0,s=this._rings.length;ot.y!=n.y>t.y&&t.x<(n.x-e.x)*(t.y-e.y)/(n.y-e.y)+e.x&&(u=!u);return u||nn.prototype._containsPoint.call(this,t,!0)}}),sn=Ke.extend({initialize:function(t,i){l(this,i),this._layers={},t&&this.addData(t)},addData:function(t){var i,e,n,o=oi(t)?t:t.features;if(o){for(i=0,e=o.length;i0?o:[i.src]}else{oi(this._url)||(this._url=[this._url]),i.autoplay=!!this.options.autoplay,i.loop=!!this.options.loop;for(var a=0;ao?(i.height=o+"px",Q(t,"leaflet-popup-scrolled")):tt(t,"leaflet-popup-scrolled"),this._containerWidth=this._container.offsetWidth},_animateZoom:function(t){var i=this._map._latLngToNewLayerPoint(this._latlng,t.zoom,t.center),e=this._getAnchor();at(this._container,i.add(e))},_adjustPan:function(){if(this.options.autoPan){this._map._panAnim&&this._map._panAnim.stop();var t=this._map,i=parseInt(q(this._container,"marginBottom"),10)||0,e=this._container.offsetHeight+i,n=this._containerWidth,o=new x(this._containerLeft,-e-this._containerBottom);o._add(ht(this._container));var s=t.layerPointToContainerPoint(o),r=w(this.options.autoPanPadding),a=w(this.options.autoPanPaddingTopLeft||r),h=w(this.options.autoPanPaddingBottomRight||r),u=t.getSize(),l=0,c=0;s.x+n+h.x>u.x&&(l=s.x+n-u.x+h.x),s.x-l-a.x<0&&(l=s.x-a.x),s.y+e+h.y>u.y&&(c=s.y+e-u.y+h.y),s.y-c-a.y<0&&(c=s.y-a.y),(l||c)&&t.fire("autopanstart").panBy([l,c])}},_onCloseButtonClick:function(t){this._close(),Lt(t)},_getAnchor:function(){return w(this._source&&this._source._getPopupAnchor?this._source._getPopupAnchor():[0,0])}});be.mergeOptions({closePopupOnClick:!0}),be.include({openPopup:function(t,i,e){return t instanceof cn||(t=new cn(e).setContent(t)),i&&t.setLatLng(i),this.hasLayer(t)?this:(this._popup&&this._popup.options.autoClose&&this.closePopup(),this._popup=t,this.addLayer(t))},closePopup:function(t){return t&&t!==this._popup||(t=this._popup,this._popup=null),t&&this.removeLayer(t),this}}),qe.include({bindPopup:function(t,i){return t instanceof cn?(l(t,i),this._popup=t,t._source=this):(this._popup&&!i||(this._popup=new cn(i,this)),this._popup.setContent(t)),this._popupHandlersAdded||(this.on({click:this._openPopup,keypress:this._onKeyPress,remove:this.closePopup,move:this._movePopup}),this._popupHandlersAdded=!0),this},unbindPopup:function(){return this._popup&&(this.off({click:this._openPopup,keypress:this._onKeyPress,remove:this.closePopup,move:this._movePopup}),this._popupHandlersAdded=!1,this._popup=null),this},openPopup:function(t,i){if(t instanceof qe||(i=t,t=this),t instanceof Ke)for(var e in this._layers){t=this._layers[e];break}return i||(i=t.getCenter?t.getCenter():t.getLatLng()),this._popup&&this._map&&(this._popup._source=t,this._popup.update(),this._map.openPopup(this._popup,i)),this},closePopup:function(){return this._popup&&this._popup._close(),this},togglePopup:function(t){return this._popup&&(this._popup._map?this.closePopup():this.openPopup(t)),this},isPopupOpen:function(){return!!this._popup&&this._popup.isOpen()},setPopupContent:function(t){return this._popup&&this._popup.setContent(t),this},getPopup:function(){return this._popup},_openPopup:function(t){var i=t.layer||t.target;this._popup&&this._map&&(Lt(t),i instanceof Qe?this.openPopup(t.layer||t.target,t.latlng):this._map.hasLayer(this._popup)&&this._popup._source===i?this.closePopup():this.openPopup(i,t.latlng))},_movePopup:function(t){this._popup.setLatLng(t.latlng)},_onKeyPress:function(t){13===t.originalEvent.keyCode&&this._openPopup(t)}});var _n=ln.extend({options:{pane:"tooltipPane",offset:[0,0],direction:"auto",permanent:!1,sticky:!1,interactive:!1,opacity:.9},onAdd:function(t){ln.prototype.onAdd.call(this,t),this.setOpacity(this.options.opacity),t.fire("tooltipopen",{tooltip:this}),this._source&&this._source.fire("tooltipopen",{tooltip:this},!0)},onRemove:function(t){ln.prototype.onRemove.call(this,t),t.fire("tooltipclose",{tooltip:this}),this._source&&this._source.fire("tooltipclose",{tooltip:this},!0)},getEvents:function(){var t=ln.prototype.getEvents.call(this);return qi&&!this.options.permanent&&(t.preclick=this._close),t},_close:function(){this._map&&this._map.closeTooltip(this)},_initLayout:function(){var t="leaflet-tooltip "+(this.options.className||"")+" leaflet-zoom-"+(this._zoomAnimated?"animated":"hide");this._contentNode=this._container=G("div",t)},_updateLayout:function(){},_adjustPan:function(){},_setPosition:function(t){var i=this._map,e=this._container,n=i.latLngToContainerPoint(i.getCenter()),o=i.layerPointToContainerPoint(t),s=this.options.direction,r=e.offsetWidth,a=e.offsetHeight,h=w(this.options.offset),u=this._getAnchor();"top"===s?t=t.add(w(-r/2+h.x,-a+h.y+u.y,!0)):"bottom"===s?t=t.subtract(w(r/2-h.x,-h.y,!0)):"center"===s?t=t.subtract(w(r/2+h.x,a/2-u.y+h.y,!0)):"right"===s||"auto"===s&&o.xthis.options.maxZoom||en&&this._retainParent(o,s,r,n))},_retainChildren:function(t,i,e,n){for(var o=2*t;o<2*t+2;o++)for(var s=2*i;s<2*i+2;s++){var r=new x(o,s);r.z=e+1;var a=this._tileCoordsToKey(r),h=this._tiles[a];h&&h.active?h.retain=!0:(h&&h.loaded&&(h.retain=!0),e+1this.options.maxZoom||void 0!==this.options.minZoom&&o1)this._setView(t,e);else{for(var c=o.min.y;c<=o.max.y;c++)for(var _=o.min.x;_<=o.max.x;_++){var d=new x(_,c);if(d.z=this._tileZoom,this._isValidTile(d)){var p=this._tiles[this._tileCoordsToKey(d)];p?p.current=!0:r.push(d)}}if(r.sort(function(t,i){return t.distanceTo(s)-i.distanceTo(s)}),0!==r.length){this._loading||(this._loading=!0,this.fire("loading"));var m=document.createDocumentFragment();for(_=0;_e.max.x)||!i.wrapLat&&(t.ye.max.y))return!1}if(!this.options.bounds)return!0;var n=this._tileCoordsToBounds(t);return z(this.options.bounds).overlaps(n)},_keyToBounds:function(t){return this._tileCoordsToBounds(this._keyToTileCoords(t))},_tileCoordsToNwSe:function(t){var i=this._map,e=this.getTileSize(),n=t.scaleBy(e),o=n.add(e);return[i.unproject(n,t.z),i.unproject(o,t.z)]},_tileCoordsToBounds:function(t){var i=this._tileCoordsToNwSe(t),e=new T(i[0],i[1]);return this.options.noWrap||(e=this._map.wrapLatLngBounds(e)),e},_tileCoordsToKey:function(t){return t.x+":"+t.y+":"+t.z},_keyToTileCoords:function(t){var i=t.split(":"),e=new x(+i[0],+i[1]);return e.z=+i[2],e},_removeTile:function(t){var i=this._tiles[t];i&&(K(i.el),delete this._tiles[t],this.fire("tileunload",{tile:i.el,coords:this._keyToTileCoords(t)}))},_initTile:function(t){Q(t,"leaflet-tile");var i=this.getTileSize();t.style.width=i.x+"px",t.style.height=i.y+"px",t.onselectstart=r,t.onmousemove=r,Li&&this.options.opacity<1&&nt(t,this.options.opacity),zi&&!Mi&&(t.style.WebkitBackfaceVisibility="hidden")},_addTile:function(t,i){var n=this._getTilePos(t),o=this._tileCoordsToKey(t),s=this.createTile(this._wrapCoords(t),e(this._tileReady,this,t));this._initTile(s),this.createTile.length<2&&f(e(this._tileReady,this,t,null,s)),at(s,n),this._tiles[o]={el:s,coords:t,current:!0},i.appendChild(s),this.fire("tileloadstart",{tile:s,coords:t})},_tileReady:function(t,i,n){i&&this.fire("tileerror",{error:i,tile:n,coords:t});var o=this._tileCoordsToKey(t);(n=this._tiles[o])&&(n.loaded=+new Date,this._map._fadeAnimated?(nt(n.el,0),g(this._fadeFrame),this._fadeFrame=f(this._updateOpacity,this)):(n.active=!0,this._pruneTiles()),i||(Q(n.el,"leaflet-tile-loaded"),this.fire("tileload",{tile:n.el,coords:t})),this._noTilesToLoad()&&(this._loading=!1,this.fire("load"),Li||!this._map._fadeAnimated?f(this._pruneTiles,this):setTimeout(e(this._pruneTiles,this),250)))},_getTilePos:function(t){return t.scaleBy(this.getTileSize()).subtract(this._level.origin)},_wrapCoords:function(t){var i=new x(this._wrapX?s(t.x,this._wrapX):t.x,this._wrapY?s(t.y,this._wrapY):t.y);return i.z=t.z,i},_pxBoundsToTileRange:function(t){var i=this.getTileSize();return new P(t.min.unscaleBy(i).floor(),t.max.unscaleBy(i).ceil().subtract([1,1]))},_noTilesToLoad:function(){for(var t in this._tiles)if(!this._tiles[t].loaded)return!1;return!0}}),mn=pn.extend({options:{minZoom:0,maxZoom:18,subdomains:"abc",errorTileUrl:"",zoomOffset:0,tms:!1,zoomReverse:!1,detectRetina:!1,crossOrigin:!1},initialize:function(t,i){this._url=t,(i=l(this,i)).detectRetina&&Yi&&i.maxZoom>0&&(i.tileSize=Math.floor(i.tileSize/2),i.zoomReverse?(i.zoomOffset--,i.minZoom++):(i.zoomOffset++,i.maxZoom--),i.minZoom=Math.max(0,i.minZoom)),"string"==typeof i.subdomains&&(i.subdomains=i.subdomains.split("")),zi||this.on("tileunload",this._onTileRemove)},setUrl:function(t,i){return this._url===t&&void 0===i&&(i=!0),this._url=t,i||this.redraw(),this},createTile:function(t,i){var n=document.createElement("img");return mt(n,"load",e(this._tileOnLoad,this,i,n)),mt(n,"error",e(this._tileOnError,this,i,n)),(this.options.crossOrigin||""===this.options.crossOrigin)&&(n.crossOrigin=!0===this.options.crossOrigin?"":this.options.crossOrigin),n.alt="",n.setAttribute("role","presentation"),n.src=this.getTileUrl(t),n},getTileUrl:function(t){var e={r:Yi?"@2x":"",s:this._getSubdomain(t),x:t.x,y:t.y,z:this._getZoomForUrl()};if(this._map&&!this._map.options.crs.infinite){var n=this._globalTileRange.max.y-t.y;this.options.tms&&(e.y=n),e["-y"]=n}return _(this._url,i(e,this.options))},_tileOnLoad:function(t,i){Li?setTimeout(e(t,this,null,i),0):t(null,i)},_tileOnError:function(t,i,e){var n=this.options.errorTileUrl;n&&i.getAttribute("src")!==n&&(i.src=n),t(e,i)},_onTileRemove:function(t){t.tile.onload=null},_getZoomForUrl:function(){var t=this._tileZoom,i=this.options.maxZoom,e=this.options.zoomReverse,n=this.options.zoomOffset;return e&&(t=i-t),t+n},_getSubdomain:function(t){var i=Math.abs(t.x+t.y)%this.options.subdomains.length;return this.options.subdomains[i]},_abortLoading:function(){var t,i;for(t in this._tiles)this._tiles[t].coords.z!==this._tileZoom&&((i=this._tiles[t].el).onload=r,i.onerror=r,i.complete||(i.src=si,K(i),delete this._tiles[t]))},_removeTile:function(t){var i=this._tiles[t];if(i)return Si||i.el.setAttribute("src",si),pn.prototype._removeTile.call(this,t)},_tileReady:function(t,i,e){if(this._map&&(!e||e.getAttribute("src")!==si))return pn.prototype._tileReady.call(this,t,i,e)}}),fn=mn.extend({defaultWmsParams:{service:"WMS",request:"GetMap",layers:"",styles:"",format:"image/jpeg",transparent:!1,version:"1.1.1"},options:{crs:null,uppercase:!1},initialize:function(t,e){this._url=t;var n=i({},this.defaultWmsParams);for(var o in e)o in this.options||(n[o]=e[o]);var s=(e=l(this,e)).detectRetina&&Yi?2:1,r=this.getTileSize();n.width=r.x*s,n.height=r.y*s,this.wmsParams=n},onAdd:function(t){this._crs=this.options.crs||t.options.crs,this._wmsVersion=parseFloat(this.wmsParams.version);var i=this._wmsVersion>=1.3?"crs":"srs";this.wmsParams[i]=this._crs.code,mn.prototype.onAdd.call(this,t)},getTileUrl:function(t){var i=this._tileCoordsToNwSe(t),e=this._crs,n=b(e.project(i[0]),e.project(i[1])),o=n.min,s=n.max,r=(this._wmsVersion>=1.3&&this._crs===Ue?[o.y,o.x,s.y,s.x]:[o.x,o.y,s.x,s.y]).join(","),a=mn.prototype.getTileUrl.call(this,t);return a+c(this.wmsParams,a,this.options.uppercase)+(this.options.uppercase?"&BBOX=":"&bbox=")+r},setParams:function(t,e){return i(this.wmsParams,t),e||this.redraw(),this}});mn.WMS=fn,Jt.wms=function(t,i){return new fn(t,i)};var gn=qe.extend({options:{padding:.1,tolerance:0},initialize:function(t){l(this,t),n(this),this._layers=this._layers||{}},onAdd:function(){this._container||(this._initContainer(),this._zoomAnimated&&Q(this._container,"leaflet-zoom-animated")),this.getPane().appendChild(this._container),this._update(),this.on("update",this._updatePaths,this)},onRemove:function(){this.off("update",this._updatePaths,this),this._destroyContainer()},getEvents:function(){var t={viewreset:this._reset,zoom:this._onZoom,moveend:this._update,zoomend:this._onZoomEnd};return this._zoomAnimated&&(t.zoomanim=this._onAnimZoom),t},_onAnimZoom:function(t){this._updateTransform(t.center,t.zoom)},_onZoom:function(){this._updateTransform(this._map.getCenter(),this._map.getZoom())},_updateTransform:function(t,i){var e=this._map.getZoomScale(i,this._zoom),n=ht(this._container),o=this._map.getSize().multiplyBy(.5+this.options.padding),s=this._map.project(this._center,i),r=this._map.project(t,i).subtract(s),a=o.multiplyBy(-e).add(n).add(o).subtract(r);ji?rt(this._container,a,e):at(this._container,a)},_reset:function(){this._update(),this._updateTransform(this._center,this._zoom);for(var t in this._layers)this._layers[t]._reset()},_onZoomEnd:function(){for(var t in this._layers)this._layers[t]._project()},_updatePaths:function(){for(var t in this._layers)this._layers[t]._update()},_update:function(){var t=this.options.padding,i=this._map.getSize(),e=this._map.containerPointToLayerPoint(i.multiplyBy(-t)).round();this._bounds=new P(e,e.add(i.multiplyBy(1+2*t)).round()),this._center=this._map.getCenter(),this._zoom=this._map.getZoom()}}),vn=gn.extend({getEvents:function(){var t=gn.prototype.getEvents.call(this);return t.viewprereset=this._onViewPreReset,t},_onViewPreReset:function(){this._postponeUpdatePaths=!0},onAdd:function(){gn.prototype.onAdd.call(this),this._draw()},_initContainer:function(){var t=this._container=document.createElement("canvas");mt(t,"mousemove",o(this._onMouseMove,32,this),this),mt(t,"click dblclick mousedown mouseup contextmenu",this._onClick,this),mt(t,"mouseout",this._handleMouseOut,this),this._ctx=t.getContext("2d")},_destroyContainer:function(){g(this._redrawRequest),delete this._ctx,K(this._container),ft(this._container),delete this._container},_updatePaths:function(){if(!this._postponeUpdatePaths){this._redrawBounds=null;for(var t in this._layers)this._layers[t]._update();this._redraw()}},_update:function(){if(!this._map._animatingZoom||!this._bounds){gn.prototype._update.call(this);var t=this._bounds,i=this._container,e=t.getSize(),n=Yi?2:1;at(i,t.min),i.width=n*e.x,i.height=n*e.y,i.style.width=e.x+"px",i.style.height=e.y+"px",Yi&&this._ctx.scale(2,2),this._ctx.translate(-t.min.x,-t.min.y),this.fire("update")}},_reset:function(){gn.prototype._reset.call(this),this._postponeUpdatePaths&&(this._postponeUpdatePaths=!1,this._updatePaths())},_initPath:function(t){this._updateDashArray(t),this._layers[n(t)]=t;var i=t._order={layer:t,prev:this._drawLast,next:null};this._drawLast&&(this._drawLast.next=i),this._drawLast=i,this._drawFirst=this._drawFirst||this._drawLast},_addPath:function(t){this._requestRedraw(t)},_removePath:function(t){var i=t._order,e=i.next,o=i.prev;e?e.prev=o:this._drawLast=o,o?o.next=e:this._drawFirst=e,delete t._order,delete this._layers[n(t)],this._requestRedraw(t)},_updatePath:function(t){this._extendRedrawBounds(t),t._project(),t._update(),this._requestRedraw(t)},_updateStyle:function(t){this._updateDashArray(t),this._requestRedraw(t)},_updateDashArray:function(t){if("string"==typeof t.options.dashArray){var i,e,n=t.options.dashArray.split(/[, ]+/),o=[];for(e=0;e')}}catch(t){return function(t){return document.createElement("<"+t+' xmlns="urn:schemas-microsoft.com:vml" class="lvml">')}}}(),xn={_initContainer:function(){this._container=G("div","leaflet-vml-container")},_update:function(){this._map._animatingZoom||(gn.prototype._update.call(this),this.fire("update"))},_initPath:function(t){var i=t._container=yn("shape");Q(i,"leaflet-vml-shape "+(this.options.className||"")),i.coordsize="1 1",t._path=yn("path"),i.appendChild(t._path),this._updateStyle(t),this._layers[n(t)]=t},_addPath:function(t){var i=t._container;this._container.appendChild(i),t.options.interactive&&t.addInteractiveTarget(i)},_removePath:function(t){var i=t._container;K(i),t.removeInteractiveTarget(i),delete this._layers[n(t)]},_updateStyle:function(t){var i=t._stroke,e=t._fill,n=t.options,o=t._container;o.stroked=!!n.stroke,o.filled=!!n.fill,n.stroke?(i||(i=t._stroke=yn("stroke")),o.appendChild(i),i.weight=n.weight+"px",i.color=n.color,i.opacity=n.opacity,n.dashArray?i.dashStyle=oi(n.dashArray)?n.dashArray.join(" "):n.dashArray.replace(/( *, *)/g," "):i.dashStyle="",i.endcap=n.lineCap.replace("butt","flat"),i.joinstyle=n.lineJoin):i&&(o.removeChild(i),t._stroke=null),n.fill?(e||(e=t._fill=yn("fill")),o.appendChild(e),e.color=n.fillColor||n.color,e.opacity=n.fillOpacity):e&&(o.removeChild(e),t._fill=null)},_updateCircle:function(t){var i=t._point.round(),e=Math.round(t._radius),n=Math.round(t._radiusY||e);this._setPath(t,t._empty()?"M0 0":"AL "+i.x+","+i.y+" "+e+","+n+" 0,23592600")},_setPath:function(t,i){t._path.v=i},_bringToFront:function(t){X(t._container)},_bringToBack:function(t){J(t._container)}},wn=$i?yn:E,Pn=gn.extend({getEvents:function(){var t=gn.prototype.getEvents.call(this);return t.zoomstart=this._onZoomStart,t},_initContainer:function(){this._container=wn("svg"),this._container.setAttribute("pointer-events","none"),this._rootGroup=wn("g"),this._container.appendChild(this._rootGroup)},_destroyContainer:function(){K(this._container),ft(this._container),delete this._container,delete this._rootGroup,delete this._svgSize},_onZoomStart:function(){this._update()},_update:function(){if(!this._map._animatingZoom||!this._bounds){gn.prototype._update.call(this);var t=this._bounds,i=t.getSize(),e=this._container;this._svgSize&&this._svgSize.equals(i)||(this._svgSize=i,e.setAttribute("width",i.x),e.setAttribute("height",i.y)),at(e,t.min),e.setAttribute("viewBox",[t.min.x,t.min.y,i.x,i.y].join(" ")),this.fire("update")}},_initPath:function(t){var i=t._path=wn("path");t.options.className&&Q(i,t.options.className),t.options.interactive&&Q(i,"leaflet-interactive"),this._updateStyle(t),this._layers[n(t)]=t},_addPath:function(t){this._rootGroup||this._initContainer(),this._rootGroup.appendChild(t._path),t.addInteractiveTarget(t._path)},_removePath:function(t){K(t._path),t.removeInteractiveTarget(t._path),delete this._layers[n(t)]},_updatePath:function(t){t._project(),t._update()},_updateStyle:function(t){var i=t._path,e=t.options;i&&(e.stroke?(i.setAttribute("stroke",e.color),i.setAttribute("stroke-opacity",e.opacity),i.setAttribute("stroke-width",e.weight),i.setAttribute("stroke-linecap",e.lineCap),i.setAttribute("stroke-linejoin",e.lineJoin),e.dashArray?i.setAttribute("stroke-dasharray",e.dashArray):i.removeAttribute("stroke-dasharray"),e.dashOffset?i.setAttribute("stroke-dashoffset",e.dashOffset):i.removeAttribute("stroke-dashoffset")):i.setAttribute("stroke","none"),e.fill?(i.setAttribute("fill",e.fillColor||e.color),i.setAttribute("fill-opacity",e.fillOpacity),i.setAttribute("fill-rule",e.fillRule||"evenodd")):i.setAttribute("fill","none"))},_updatePoly:function(t,i){this._setPath(t,k(t._parts,i))},_updateCircle:function(t){var i=t._point,e=Math.max(Math.round(t._radius),1),n="a"+e+","+(Math.max(Math.round(t._radiusY),1)||e)+" 0 1,0 ",o=t._empty()?"M0 0":"M"+(i.x-e)+","+i.y+n+2*e+",0 "+n+2*-e+",0 ";this._setPath(t,o)},_setPath:function(t,i){t._path.setAttribute("d",i)},_bringToFront:function(t){X(t._path)},_bringToBack:function(t){J(t._path)}});$i&&Pn.include(xn),be.include({getRenderer:function(t){var i=t.options.renderer||this._getPaneRenderer(t.options.pane)||this.options.renderer||this._renderer;return i||(i=this._renderer=this._createRenderer()),this.hasLayer(i)||this.addLayer(i),i},_getPaneRenderer:function(t){if("overlayPane"===t||void 0===t)return!1;var i=this._paneRenderers[t];return void 0===i&&(i=this._createRenderer({pane:t}),this._paneRenderers[t]=i),i},_createRenderer:function(t){return this.options.preferCanvas&&$t(t)||Qt(t)}});var Ln=on.extend({initialize:function(t,i){on.prototype.initialize.call(this,this._boundsToLatLngs(t),i)},setBounds:function(t){return this.setLatLngs(this._boundsToLatLngs(t))},_boundsToLatLngs:function(t){return t=z(t),[t.getSouthWest(),t.getNorthWest(),t.getNorthEast(),t.getSouthEast()]}});Pn.create=wn,Pn.pointsToPath=k,sn.geometryToLayer=Ft,sn.coordsToLatLng=Ut,sn.coordsToLatLngs=Vt,sn.latLngToCoords=qt,sn.latLngsToCoords=Gt,sn.getFeature=Kt,sn.asFeature=Yt,be.mergeOptions({boxZoom:!0});var bn=Ee.extend({initialize:function(t){this._map=t,this._container=t._container,this._pane=t._panes.overlayPane,this._resetStateTimeout=0,t.on("unload",this._destroy,this)},addHooks:function(){mt(this._container,"mousedown",this._onMouseDown,this)},removeHooks:function(){ft(this._container,"mousedown",this._onMouseDown,this)},moved:function(){return this._moved},_destroy:function(){K(this._pane),delete this._pane},_resetState:function(){this._resetStateTimeout=0,this._moved=!1},_clearDeferredResetState:function(){0!==this._resetStateTimeout&&(clearTimeout(this._resetStateTimeout),this._resetStateTimeout=0)},_onMouseDown:function(t){if(!t.shiftKey||1!==t.which&&1!==t.button)return!1;this._clearDeferredResetState(),this._resetState(),fi(),ut(),this._startPoint=this._map.mouseEventToContainerPoint(t),mt(document,{contextmenu:Lt,mousemove:this._onMouseMove,mouseup:this._onMouseUp,keydown:this._onKeyDown},this)},_onMouseMove:function(t){this._moved||(this._moved=!0,this._box=G("div","leaflet-zoom-box",this._container),Q(this._container,"leaflet-crosshair"),this._map.fire("boxzoomstart")),this._point=this._map.mouseEventToContainerPoint(t);var i=new P(this._point,this._startPoint),e=i.getSize();at(this._box,i.min),this._box.style.width=e.x+"px",this._box.style.height=e.y+"px"},_finish:function(){this._moved&&(K(this._box),tt(this._container,"leaflet-crosshair")),gi(),lt(),ft(document,{contextmenu:Lt,mousemove:this._onMouseMove,mouseup:this._onMouseUp,keydown:this._onKeyDown},this)},_onMouseUp:function(t){if((1===t.which||1===t.button)&&(this._finish(),this._moved)){this._clearDeferredResetState(),this._resetStateTimeout=setTimeout(e(this._resetState,this),0);var i=new T(this._map.containerPointToLatLng(this._startPoint),this._map.containerPointToLatLng(this._point));this._map.fitBounds(i).fire("boxzoomend",{boxZoomBounds:i})}},_onKeyDown:function(t){27===t.keyCode&&this._finish()}});be.addInitHook("addHandler","boxZoom",bn),be.mergeOptions({doubleClickZoom:!0});var Tn=Ee.extend({addHooks:function(){this._map.on("dblclick",this._onDoubleClick,this)},removeHooks:function(){this._map.off("dblclick",this._onDoubleClick,this)},_onDoubleClick:function(t){var i=this._map,e=i.getZoom(),n=i.options.zoomDelta,o=t.originalEvent.shiftKey?e-n:e+n;"center"===i.options.doubleClickZoom?i.setZoom(o):i.setZoomAround(t.containerPoint,o)}});be.addInitHook("addHandler","doubleClickZoom",Tn),be.mergeOptions({dragging:!0,inertia:!Mi,inertiaDeceleration:3400,inertiaMaxSpeed:1/0,easeLinearity:.2,worldCopyJump:!1,maxBoundsViscosity:0});var zn=Ee.extend({addHooks:function(){if(!this._draggable){var t=this._map;this._draggable=new Re(t._mapPane,t._container),this._draggable.on({dragstart:this._onDragStart,drag:this._onDrag,dragend:this._onDragEnd},this),this._draggable.on("predrag",this._onPreDragLimit,this),t.options.worldCopyJump&&(this._draggable.on("predrag",this._onPreDragWrap,this),t.on("zoomend",this._onZoomEnd,this),t.whenReady(this._onZoomEnd,this))}Q(this._map._container,"leaflet-grab leaflet-touch-drag"),this._draggable.enable(),this._positions=[],this._times=[]},removeHooks:function(){tt(this._map._container,"leaflet-grab"),tt(this._map._container,"leaflet-touch-drag"),this._draggable.disable()},moved:function(){return this._draggable&&this._draggable._moved},moving:function(){return this._draggable&&this._draggable._moving},_onDragStart:function(){var t=this._map;if(t._stop(),this._map.options.maxBounds&&this._map.options.maxBoundsViscosity){var i=z(this._map.options.maxBounds);this._offsetLimit=b(this._map.latLngToContainerPoint(i.getNorthWest()).multiplyBy(-1),this._map.latLngToContainerPoint(i.getSouthEast()).multiplyBy(-1).add(this._map.getSize())),this._viscosity=Math.min(1,Math.max(0,this._map.options.maxBoundsViscosity))}else this._offsetLimit=null;t.fire("movestart").fire("dragstart"),t.options.inertia&&(this._positions=[],this._times=[])},_onDrag:function(t){if(this._map.options.inertia){var i=this._lastTime=+new Date,e=this._lastPos=this._draggable._absPos||this._draggable._newPos;this._positions.push(e),this._times.push(i),this._prunePositions(i)}this._map.fire("move",t).fire("drag",t)},_prunePositions:function(t){for(;this._positions.length>1&&t-this._times[0]>50;)this._positions.shift(),this._times.shift()},_onZoomEnd:function(){var t=this._map.getSize().divideBy(2),i=this._map.latLngToLayerPoint([0,0]);this._initialWorldOffset=i.subtract(t).x,this._worldWidth=this._map.getPixelWorldBounds().getSize().x},_viscousLimit:function(t,i){return t-(t-i)*this._viscosity},_onPreDragLimit:function(){if(this._viscosity&&this._offsetLimit){var t=this._draggable._newPos.subtract(this._draggable._startPos),i=this._offsetLimit;t.xi.max.x&&(t.x=this._viscousLimit(t.x,i.max.x)),t.y>i.max.y&&(t.y=this._viscousLimit(t.y,i.max.y)),this._draggable._newPos=this._draggable._startPos.add(t)}},_onPreDragWrap:function(){var t=this._worldWidth,i=Math.round(t/2),e=this._initialWorldOffset,n=this._draggable._newPos.x,o=(n-i+e)%t+i-e,s=(n+i+e)%t-i-e,r=Math.abs(o+e)0?s:-s))-i;this._delta=0,this._startTime=null,r&&("center"===t.options.scrollWheelZoom?t.setZoom(i+r):t.setZoomAround(this._lastMousePos,i+r))}});be.addInitHook("addHandler","scrollWheelZoom",Cn),be.mergeOptions({tap:!0,tapTolerance:15});var Sn=Ee.extend({addHooks:function(){mt(this._map._container,"touchstart",this._onDown,this)},removeHooks:function(){ft(this._map._container,"touchstart",this._onDown,this)},_onDown:function(t){if(t.touches){if(Pt(t),this._fireClick=!0,t.touches.length>1)return this._fireClick=!1,void clearTimeout(this._holdTimeout);var i=t.touches[0],n=i.target;this._startPos=this._newPos=new x(i.clientX,i.clientY),n.tagName&&"a"===n.tagName.toLowerCase()&&Q(n,"leaflet-active"),this._holdTimeout=setTimeout(e(function(){this._isTapValid()&&(this._fireClick=!1,this._onUp(),this._simulateEvent("contextmenu",i))},this),1e3),this._simulateEvent("mousedown",i),mt(document,{touchmove:this._onMove,touchend:this._onUp},this)}},_onUp:function(t){if(clearTimeout(this._holdTimeout),ft(document,{touchmove:this._onMove,touchend:this._onUp},this),this._fireClick&&t&&t.changedTouches){var i=t.changedTouches[0],e=i.target;e&&e.tagName&&"a"===e.tagName.toLowerCase()&&tt(e,"leaflet-active"),this._simulateEvent("mouseup",i),this._isTapValid()&&this._simulateEvent("click",i)}},_isTapValid:function(){return this._newPos.distanceTo(this._startPos)<=this._map.options.tapTolerance},_onMove:function(t){var i=t.touches[0];this._newPos=new x(i.clientX,i.clientY),this._simulateEvent("mousemove",i)},_simulateEvent:function(t,i){var e=document.createEvent("MouseEvents");e._simulated=!0,i.target._simulatedClick=!0,e.initMouseEvent(t,!0,!0,window,1,i.screenX,i.screenY,i.clientX,i.clientY,!1,!1,!1,!1,0,null),i.target.dispatchEvent(e)}});qi&&!Vi&&be.addInitHook("addHandler","tap",Sn),be.mergeOptions({touchZoom:qi&&!Mi,bounceAtZoomLimits:!0});var Zn=Ee.extend({addHooks:function(){Q(this._map._container,"leaflet-touch-zoom"),mt(this._map._container,"touchstart",this._onTouchStart,this)},removeHooks:function(){tt(this._map._container,"leaflet-touch-zoom"),ft(this._map._container,"touchstart",this._onTouchStart,this)},_onTouchStart:function(t){var i=this._map;if(t.touches&&2===t.touches.length&&!i._animatingZoom&&!this._zooming){var e=i.mouseEventToContainerPoint(t.touches[0]),n=i.mouseEventToContainerPoint(t.touches[1]);this._centerPoint=i.getSize()._divideBy(2),this._startLatLng=i.containerPointToLatLng(this._centerPoint),"center"!==i.options.touchZoom&&(this._pinchStartLatLng=i.containerPointToLatLng(e.add(n)._divideBy(2))),this._startDist=e.distanceTo(n),this._startZoom=i.getZoom(),this._moved=!1,this._zooming=!0,i._stop(),mt(document,"touchmove",this._onTouchMove,this),mt(document,"touchend",this._onTouchEnd,this),Pt(t)}},_onTouchMove:function(t){if(t.touches&&2===t.touches.length&&this._zooming){var i=this._map,n=i.mouseEventToContainerPoint(t.touches[0]),o=i.mouseEventToContainerPoint(t.touches[1]),s=n.distanceTo(o)/this._startDist;if(this._zoom=i.getScaleZoom(s,this._startZoom),!i.options.bounceAtZoomLimits&&(this._zoomi.getMaxZoom()&&s>1)&&(this._zoom=i._limitZoom(this._zoom)),"center"===i.options.touchZoom){if(this._center=this._startLatLng,1===s)return}else{var r=n._add(o)._divideBy(2)._subtract(this._centerPoint);if(1===s&&0===r.x&&0===r.y)return;this._center=i.unproject(i.project(this._pinchStartLatLng,this._zoom).subtract(r),this._zoom)}this._moved||(i._moveStart(!0,!1),this._moved=!0),g(this._animRequest);var a=e(i._move,i,this._center,this._zoom,{pinch:!0,round:!1});this._animRequest=f(a,this,!0),Pt(t)}},_onTouchEnd:function(){this._moved&&this._zooming?(this._zooming=!1,g(this._animRequest),ft(document,"touchmove",this._onTouchMove),ft(document,"touchend",this._onTouchEnd),this._map.options.zoomAnimation?this._map._animateZoom(this._center,this._map._limitZoom(this._zoom),!0,this._map.options.zoomSnap):this._map._resetView(this._center,this._map._limitZoom(this._zoom))):this._zooming=!1}});be.addInitHook("addHandler","touchZoom",Zn),be.BoxZoom=bn,be.DoubleClickZoom=Tn,be.Drag=zn,be.Keyboard=Mn,be.ScrollWheelZoom=Cn,be.Tap=Sn,be.TouchZoom=Zn,Object.freeze=ti,t.version="1.4.0+HEAD.3337f36",t.Control=Te,t.control=ze,t.Browser=Qi,t.Evented=ci,t.Mixin=Be,t.Util=ui,t.Class=v,t.Handler=Ee,t.extend=i,t.bind=e,t.stamp=n,t.setOptions=l,t.DomEvent=Pe,t.DomUtil=ve,t.PosAnimation=Le,t.Draggable=Re,t.LineUtil=Ne,t.PolyUtil=De,t.Point=x,t.point=w,t.Bounds=P,t.bounds=b,t.Transformation=S,t.transformation=Z,t.Projection=He,t.LatLng=M,t.latLng=C,t.LatLngBounds=T,t.latLngBounds=z,t.CRS=di,t.GeoJSON=sn,t.geoJSON=Xt,t.geoJson=an,t.Layer=qe,t.LayerGroup=Ge,t.layerGroup=function(t,i){return new Ge(t,i)},t.FeatureGroup=Ke,t.featureGroup=function(t){return new Ke(t)},t.ImageOverlay=hn,t.imageOverlay=function(t,i,e){return new hn(t,i,e)},t.VideoOverlay=un,t.videoOverlay=function(t,i,e){return new un(t,i,e)},t.DivOverlay=ln,t.Popup=cn,t.popup=function(t,i){return new cn(t,i)},t.Tooltip=_n,t.tooltip=function(t,i){return new _n(t,i)},t.Icon=Ye,t.icon=function(t){return new Ye(t)},t.DivIcon=dn,t.divIcon=function(t){return new dn(t)},t.Marker=$e,t.marker=function(t,i){return new $e(t,i)},t.TileLayer=mn,t.tileLayer=Jt,t.GridLayer=pn,t.gridLayer=function(t){return new pn(t)},t.SVG=Pn,t.svg=Qt,t.Renderer=gn,t.Canvas=vn,t.canvas=$t,t.Path=Qe,t.CircleMarker=tn,t.circleMarker=function(t,i){return new tn(t,i)},t.Circle=en,t.circle=function(t,i,e){return new en(t,i,e)},t.Polyline=nn,t.polyline=function(t,i){return new nn(t,i)},t.Polygon=on,t.polygon=function(t,i){return new on(t,i)},t.Rectangle=Ln,t.rectangle=function(t,i){return new Ln(t,i)},t.Map=be,t.map=function(t,i){return new be(t,i)};var En=window.L;t.noConflict=function(){return window.L=En,this},window.L=t});
\ No newline at end of file
diff --git a/odex30_base/odex30_web_map/static/src/js/map_controller.js b/odex30_base/odex30_web_map/static/src/js/map_controller.js
new file mode 100644
index 0000000..f50b357
--- /dev/null
+++ b/odex30_base/odex30_web_map/static/src/js/map_controller.js
@@ -0,0 +1,131 @@
+odoo.define('odex30_web_map.MapController', function (require) {
+"use strict";
+
+const AbstractController = require('web.AbstractController');
+const core = require('web.core');
+const qweb = core.qweb;
+
+const MapController = AbstractController.extend({
+ custom_events: _.extend({}, AbstractController.prototype.custom_events, {
+ 'pin_clicked': '_onPinClick',
+ 'get_itinerary_clicked': '_onGetItineraryClicked',
+ 'open_clicked': '_onOpenClicked',
+ 'pager_changed': '_onPagerChanged',
+ 'coordinate_fetched': '_onCoordinateFetched',
+ }),
+
+ /**
+ * @constructor
+ */
+ init: function (parent, model, renderer, params) {
+ this._super.apply(this, arguments);
+ this.actionName = params.actionName;
+ },
+
+ //--------------------------------------------------------------------------
+ // Public
+ //--------------------------------------------------------------------------
+
+ /**
+ * @override
+ * @param {jQuery} [$node]
+ */
+ renderButtons: function ($node) {
+ let url = 'https://www.google.com/maps/dir/?api=1';
+ if (this.model.data.records.length) {
+ const coordinates = this.model.data.records
+ .filter(record => record.partner && record.partner.partner_latitude && record.partner.partner_longitude)
+ .map(record => record.partner.partner_latitude + ',' + record.partner.partner_longitude);
+ url += `&waypoints=${_.uniq(coordinates).join('|')}`;
+ }
+ this.$buttons = $(qweb.render("MapView.buttons"), { widget: this });
+ this.$buttons.find('a').attr('href', url);
+ if ($node) {
+ this.$buttons.appendTo($node);
+ }
+ },
+ /**
+ * @override
+ */
+ update: async function () {
+ await this._super(...arguments);
+ this._updatePaging();
+ },
+
+ //--------------------------------------------------------------------------
+ // Private
+ //--------------------------------------------------------------------------
+
+ /**
+ * Return the params (currentMinimum, limit and size) to pass to the pager,
+ * according to the current state.
+ *
+ * @private
+ * @returns {Object}
+ */
+ _getPagingInfo: function () {
+ const state = this.model.get();
+ return {
+ currentMinimum: state.offset + 1,
+ limit: state.limit,
+ size: state.count,
+ };
+ },
+
+ //--------------------------------------------------------------------------
+ // Handlers
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ * @param {OdooEvent} ev
+ */
+ _onCoordinateFetched: function (ev) {
+ ev.stopPropagation();
+ this.update({}, { reload: false });
+ },
+ /**
+ * Redirects to google maps with all the records' coordinates.
+ *
+ * @private
+ * @param {MouseEvent} ev
+ */
+ _onGetItineraryClicked: function (ev) {
+ window.open(`https://www.google.com/maps/dir/?api=1&destination=${ev.data.lat},${ev.data.lon}`);
+ },
+ /**
+ * Redirects to views when clicked on open button in marker popup.
+ *
+ * @private
+ * @param {MouseEvent} ev
+ */
+ _onOpenClicked: function (ev) {
+ if (ev.data.ids.length > 1) {
+ this.do_action({
+ type: 'ir.actions.act_window',
+ name: this.actionName,
+ views: [[false, 'list'], [false, 'form']],
+ res_model: this.modelName,
+ domain: [['id', 'in', ev.data.ids]],
+ });
+ } else {
+ this.trigger_up('switch_view', {
+ view_type: 'form',
+ res_id: ev.data.ids[0],
+ mode: 'readonly',
+ model: this.modelName
+ });
+ }
+ },
+ /**
+ * @private
+ * @param {OdooEvent} ev
+ */
+ async _onPagerChanged(ev) {
+ const { currentMinimum, limit } = ev.data;
+ await this.reload({ limit, offset: currentMinimum - 1 });
+ },
+});
+
+return MapController;
+});
diff --git a/odex30_base/odex30_web_map/static/src/js/map_model.js b/odex30_base/odex30_web_map/static/src/js/map_model.js
new file mode 100644
index 0000000..68edc49
--- /dev/null
+++ b/odex30_base/odex30_web_map/static/src/js/map_model.js
@@ -0,0 +1,505 @@
+odoo.define('odex30_web_map.MapModel', function (require) {
+"use strict";
+
+const AbstractModel = require('web.AbstractModel');
+const session = require('web.session');
+const core = require('web.core');
+const _t = core._t;
+
+const MapModel = AbstractModel.extend({
+ // Used in _openStreetMapAPIAsync to add delay between coordinates fetches
+ // We need this delay to not get banned from OSM.
+ COORDINATE_FETCH_DELAY: 1000,
+
+ //--------------------------------------------------------------------------
+ // Public
+ //--------------------------------------------------------------------------
+
+ /**
+ * @constructor
+ */
+ init: function () {
+ this._super.apply(this, arguments);
+ this.data = {};
+ this.data.mapBoxToken = session.map_box_token;
+ },
+ __get: function () {
+ return this.data;
+ },
+ __load: function (params) {
+ this.data.count = 0;
+ this.data.offset = 0;
+ this.data.limit = params.limit;
+ this.partnerToCache = [];
+ this.partnerIds = [];
+ this.resPartnerField = params.resPartnerField;
+ this.model = params.modelName;
+ this.context = params.context;
+ this.fields = params.fieldNames;
+ this.fieldsInfo = params.fieldsInfo;
+ this.domain = params.domain;
+ this.params = params;
+ this.orderBy = params.orderBy;
+ this.routing = params.routing;
+ this.numberOfLocatedRecords = 0;
+ this.coordinateFetchingTimeoutHandle = undefined;
+ this.data.shouldUpdatePosition = true;
+ this.data.fetchingCoordinates = false;
+ this.data.groupBy = params.groupedBy.length ? params.groupedBy[0] : false;
+ return this._fetchData();
+ },
+ __reload: function (handle, params) {
+ const options = params || {};
+ this.partnerToCache = [];
+ this.partnerIds = [];
+ this.numberOfLocatedRecords = 0;
+ this.data.shouldUpdatePosition = true;
+ this.data.fetchingCoordinates = false;
+ if (this.coordinateFetchingTimeoutHandle !== undefined) {
+ clearInterval(this.coordinateFetchingTimeoutHandle);
+ this.coordinateFetchingTimeoutHandle = undefined;
+ }
+ if (options.domain !== undefined) {
+ this.domain = options.domain;
+ }
+ if (options.limit !== undefined) {
+ this.data.limit = options.limit;
+ }
+ if (options.offset !== undefined) {
+ this.data.offset = options.offset;
+ }
+ if (options.groupBy !== undefined && options.groupBy[0] !== this.data.groupBy) {
+ this.data.groupBy = options.groupBy.length ? options.groupBy[0] : false;
+ }
+ return this._fetchData();
+ },
+
+ //--------------------------------------------------------------------------
+ // Private
+ //--------------------------------------------------------------------------
+
+ /**
+ * Adds the corresponding partner to a record.
+ *
+ * @private
+ */
+ _addPartnerToRecord: function () {
+ this.data.records.forEach((record) => {
+ this.data.partners.forEach((partner) => {
+ let recordPartnerId;
+ if (this.model === "res.partner" && this.resPartnerField === "id") {
+ recordPartnerId = record.id;
+ } else {
+ recordPartnerId = record[this.resPartnerField][0];
+ }
+
+ if (recordPartnerId == partner.id) {
+ record.partner = partner;
+ this.numberOfLocatedRecords++;
+ }
+ });
+ });
+ },
+ /**
+ * The partner's coordinates should be between -90 <= latitude <= 90 and -180 <= longitude <= 180.
+ *
+ * @private
+ * @param {Object} partner
+ * @param {float} partner.partner_latitude latitude of the partner
+ * @param {float} partner.partner_longitude longitude of the partner
+ * @returns {boolean}
+ */
+ _checkCoordinatesValidity: function (partner) {
+ if (partner.partner_latitude && partner.partner_longitude &&
+ partner.partner_latitude >= -90 && partner.partner_latitude <= 90 &&
+ partner.partner_longitude >= -180 && partner.partner_longitude <= 180) {
+ return true;
+ }
+ return false;
+ },
+ /**
+ * This function convert the addresses to coordinates using the mapbox API.
+ *
+ * @private
+ * @param {Object} record this object contains the record fetched from the database.
+ * @returns {Promise} result.query contains the query the the api received
+ * result.features contains results in descendant order of relevance
+ */
+ _fetchCoordinatesFromAddressMB: function (record) {
+ const address = encodeURIComponent(record.contact_address_complete);
+ const token = this.data.mapBoxToken;
+ const encodedUrl = `https://api.mapbox.com/geocoding/v5/mapbox.places/${address}.json?access_token=${token}&cachebuster=1552314159970&autocomplete=true`;
+ return new Promise((resolve, reject) => {
+ $.get(encodedUrl).then(resolve).catch(reject);
+ });
+ },
+ /**
+ * This function convert the addresses to coordinates using the openStreetMap api.
+ *
+ * @private
+ * @param {Object} record this object contains the record fetched from the database.
+ * @returns {Promise} result is an array that contains the result in descendant order of relevance
+ * result[i].lat is the latitude of the converted address
+ * result[i].lon is the longitude of the converted address
+ * result[i].importance is a float that the relevance of the result the closer the float is to one the best it is.
+ */
+ _fetchCoordinatesFromAddressOSM: function (record) {
+ const address = encodeURIComponent(record.contact_address_complete.replace('/', ' '));
+ const encodedUrl = `https://nominatim.openstreetmap.org/search/${address}?format=jsonv2`;
+ return new Promise(function (resolve, reject) {
+ $.get(encodedUrl).then(resolve).catch(reject);
+ });
+ },
+ /**
+ * Handles the case of an empty map.
+ * Handles the case where the model is res_partner.
+ * Fetches the records according to the model given in the arch.
+ * If the records has no partner_id field it is sliced from the array.
+ *
+ * @private
+ * @return {Promise}
+ */
+ _fetchData: async function () {
+ //case of empty map
+ if (!this.resPartnerField) {
+ this.data.recordGroups = [];
+ this.data.records = [];
+ this.data.routeInfo = { routes: [] };
+ return;
+ }
+ const results = await this._fetchRecordData();
+ this.data.records = results.records;
+ this.data.count = results.length;
+ if (this.data.groupBy) {
+ this.data.recordGroups = this._getRecordGroups();
+ } else {
+ this.data.recordGroups = {};
+ }
+
+ this.partnerIds = [];
+ if (this.model === "res.partner" && this.resPartnerField === "id") {
+ this.data.records.forEach((record) => {
+ this.partnerIds.push(record.id);
+ record.partner_id = [record.id];
+ });
+ } else {
+ this._fillPartnerIds(this.data.records);
+ }
+
+ this.partnerIds = _.uniq(this.partnerIds);
+ return this._partnerFetching(this.partnerIds);
+ },
+ /**
+ * Fetch the records for a given model.
+ *
+ * @private
+ * @returns {Promise}
+ */
+ _fetchRecordData: function () {
+ return this._rpc({
+ route: '/web/dataset/search_read',
+ model: this.model,
+ context: this.context,
+ fields: this.data.groupBy ?
+ this.fields.concat(this.data.groupBy.split(':')[0]) :
+ this.fields,
+ domain: this.domain,
+ orderBy: this.orderBy,
+ limit: this.data.limit,
+ offset: this.data.offset
+ });
+ },
+ /**
+ * @private
+ * @returns {Object} the fetched records grouped by the groupBy field.
+ */
+ _getRecordGroups: function () {
+ const [fieldName, subGroup] = this.data.groupBy.split(':');
+ const dateGroupFormats = {
+ year: 'YYYY',
+ quarter: '[Q]Q YYYY',
+ month: 'MMMM YYYY',
+ week: '[W]WW YYYY',
+ day: 'DD MMM YYYY',
+ };
+ const groups = {};
+ for (const record of this.data.records) {
+ const value = record[fieldName];
+ let id, name;
+ if (['date', 'datetime'].includes(this.fieldsInfo[fieldName].type)) {
+ const date = moment(value);
+ id = name = date.format(dateGroupFormats[subGroup]);
+ } else {
+ id = Array.isArray(value) ? value[0] : value;
+ name = Array.isArray(value) ? value[1] : value;
+ }
+ if (!groups[id]) {
+ groups[id] = {
+ name,
+ records: [],
+ };
+ }
+ groups[id].records.push(record);
+ }
+ return groups;
+ },
+ /**
+ * @private
+ * @param {Number[]} ids contains the ids from the partners
+ * @returns {Promise}
+ */
+ _fetchRecordsPartner: function (ids) {
+ return this._rpc({
+ model: 'res.partner',
+ method: 'search_read',
+ fields: ['contact_address_complete', 'partner_latitude', 'partner_longitude'],
+ domain: [['contact_address_complete', '!=', 'False'], ['id', 'in', ids]],
+ });
+ },
+ /**
+ * Fetch the route from the mapbox api.
+ *
+ * @private
+ * @returns {Promise}
+ * results.geometry.legs[i] contains one leg (i.e: the trip between two markers).
+ * results.geometry.legs[i].steps contains the sets of coordinates to follow to reach a point from an other.
+ * results.geometry.legs[i].distance: the distance in meters to reach the destination
+ * results.geometry.legs[i].duration the duration of the leg
+ * results.geometry.coordinates contains the sets of coordinates to go from the first to the last marker without the notion of waypoint
+ */
+ _fetchRoute: function () {
+ const coordinatesParam = this.data.records
+ .filter(record => record.partner.partner_latitude && record.partner.partner_longitude)
+ .map(record => record.partner.partner_longitude + ',' + record.partner.partner_latitude);
+ const address = encodeURIComponent(coordinatesParam.join(';'));
+ const token = this.data.mapBoxToken;
+ const encodedUrl = `https://api.mapbox.com/directions/v5/mapbox/driving/${address}?access_token=${token}&steps=true&geometries=geojson`;
+ return new Promise(function (resolve, reject) {
+ $.get(encodedUrl).then(resolve).catch(reject);
+ });
+ },
+ /**
+ * @private
+ * @param {Object[]} records the records that are going to be filtered
+ * @returns {Object[]} Array of records that contains a partner_id
+ */
+ _fillPartnerIds: function (records) {
+ return records.forEach(record => {
+ if (record[this.resPartnerField]) {
+ this.partnerIds.push(record[this.resPartnerField][0]);
+ }
+ });
+ },
+ /**
+ * Converts a MapBox error message into a custom translatable one.
+ *
+ * @private
+ * @param {string} message
+ */
+ _getErrorMessage: function (message) {
+ const ERROR_MESSAGES = {
+ 'Too many coordinates; maximum number of coordinates is 25': _t("Too many routing points (maximum 25)"),
+ 'Route exceeds maximum distance limitation': _t("Some routing points are too far apart"),
+ 'Too Many Requests': _t("Too many requests, try again in a few minutes"),
+ };
+ return ERROR_MESSAGES[message];
+ },
+ /**
+ * Handles the case where the selected api is MapBox.
+ * Iterates on all the partners and fetches their coordinates when they're not set.
+ *
+ * @private
+ * @return {Promise | Promise<>} if there's more than 2 located records and the routing option is activated it returns a promise that fetches the route
+ * resultResult is an object that contains the computed route
+ * or if either of these conditions are not respected it returns an empty promise
+ */
+ _maxBoxAPI: function () {
+ const promises = [];
+ this.data.partners.forEach(partner => {
+ if (partner.contact_address_complete && (!partner.partner_latitude || !partner.partner_longitude)) {
+ promises.push(this._fetchCoordinatesFromAddressMB(partner).then(coordinates => {
+ if (coordinates.features.length) {
+ partner.partner_longitude = coordinates.features[0].geometry.coordinates[0];
+ partner.partner_latitude = coordinates.features[0].geometry.coordinates[1];
+ this.partnerToCache.push(partner);
+ }
+ }));
+ } else if (!this._checkCoordinatesValidity(partner)) {
+ partner.partner_latitude = undefined;
+ partner.partner_longitude = undefined;
+ }
+ });
+ return Promise.all(promises).then(() => {
+ this.data.routeInfo = { routes: [] };
+ if (this.numberOfLocatedRecords > 1 && this.routing && !this.data.groupBy) {
+ return this._fetchRoute().then(routeResult => {
+ if (routeResult.routes) {
+ this.data.routeInfo = routeResult;
+ } else {
+ this.data.routingError = this._getErrorMessage(routeResult.message);
+ }
+ });
+ } else {
+ return Promise.resolve();
+ }
+ });
+ },
+ /**
+ * Handles the displaying of error message according to the error.
+ *
+ * @private
+ * @param {Object} err contains the error returned by the requests
+ * @param {Number} err.status contains the status_code of the failed http request
+ */
+ _mapBoxErrorHandling: function (err) {
+ switch (err.status) {
+ case 401:
+ this.do_warn(
+ _t('Token invalid'),
+ _t('The view has switched to another provider but functionalities will be limited')
+ );
+ break;
+ case 403:
+ this.do_warn(
+ _t('Unauthorized connection'),
+ _t('The view has switched to another provider but functionalities will be limited')
+ );
+ break;
+ case 422: // Max. addresses reached
+ case 429: // Max. requests reached
+ this.data.routingError = this._getErrorMessage(err.responseJSON.message);
+ break;
+ case 500:
+ this.do_warn(
+ _t('MapBox servers unreachable'),
+ _t('The view has switched to another provider but functionalities will be limited')
+ );
+ }
+ },
+ /**
+ * Notifies the fetched coordinates to server and controller.
+ *
+ * @private
+ */
+ _notifyFetchedCoordinate: function () {
+ this._writeCoordinatesUsers();
+ this.data.shouldUpdatePosition = false;
+ this.trigger_up('coordinate_fetched');
+ },
+ /**
+ * Calls (without awaiting) _openStreetMapAPIAsync with a delay of 1000ms
+ * to not get banned from openstreetmap's server.
+ *
+ * Tests should patch this function to wait for coords to be fetched.
+ *
+ * @see _openStreetMapAPIAsync
+ * @private
+ * @return {Promise}
+ */
+ _openStreetMapAPI: function () {
+ this._openStreetMapAPIAsync();
+ return Promise.resolve();
+ },
+ /**
+ * Handles the case where the selected api is open street map.
+ * Iterates on all the partners and fetches their coordinates when they're not set.
+ *
+ * @private
+ * @returns {Promise}
+ */
+ _openStreetMapAPIAsync: function () {
+ // Group partners by address to reduce address list
+ const addressPartnerMap = new Map();
+ for (const partner of this.data.partners) {
+ if (partner.contact_address_complete && (!partner.partner_latitude || !partner.partner_longitude)) {
+ if (!addressPartnerMap.has(partner.contact_address_complete)) {
+ addressPartnerMap.set(partner.contact_address_complete, []);
+ }
+ addressPartnerMap.get(partner.contact_address_complete).push(partner);
+ partner.fetchingCoordinate = true;
+ } else if (!this._checkCoordinatesValidity(partner)) {
+ partner.partner_latitude = undefined;
+ partner.partner_longitude = undefined;
+ }
+ }
+
+ // `fetchingCoordinates` is used to display the "fetching banner"
+ // We need to check if there are coordinates to fetch before reload the
+ // view to prevent flickering
+ this.data.fetchingCoordinates = addressPartnerMap.size > 0;
+ const fetch = async () => {
+ const partnersList = Array.from(addressPartnerMap.values());
+ for (let i = 0; i < partnersList.length; i++) {
+ const partners = partnersList[i];
+ try {
+ const coordinates = await this._fetchCoordinatesFromAddressOSM(partners[0]);
+ if (coordinates.length) {
+ for (const partner of partners) {
+ partner.partner_longitude = coordinates[0].lon;
+ partner.partner_latitude = coordinates[0].lat;
+ this.partnerToCache.push(partner);
+ }
+ }
+ } finally {
+ for (const partner of partners) {
+ partner.fetchingCoordinate = false;
+ }
+ this.data.fetchingCoordinates = (i < partnersList.length - 1);
+ this._notifyFetchedCoordinate();
+ await new Promise((resolve) => {
+ this.coordinateFetchingTimeoutHandle =
+ setTimeout(resolve, this.COORDINATE_FETCH_DELAY);
+ });
+ }
+ }
+ }
+ return fetch();
+ },
+ /**
+ * Fetches the partner which ids are contained in the the array partnerids
+ * if the token is set it uses the mapBoxApi to fetch address and route
+ * if not is uses the openstreetmap api to fetch the address.
+ *
+ * @private
+ * @param {number[]} partnerIds this array contains the ids from the partner that are linked to records
+ * @returns {Promise}
+ */
+ _partnerFetching: async function (partnerIds) {
+ this.data.partners = partnerIds.length ? await this._fetchRecordsPartner(partnerIds) : [];
+ this._addPartnerToRecord();
+ if (this.data.mapBoxToken) {
+ return this._maxBoxAPI()
+ .then(() => {
+ this._writeCoordinatesUsers();
+ }).catch((err) => {
+ this._mapBoxErrorHandling(err);
+ this.data.mapBoxToken = '';
+ return this._openStreetMapAPI();
+ });
+ } else {
+ return this._openStreetMapAPI().then(() => {
+ this._writeCoordinatesUsers();
+ });
+ }
+ },
+ /**
+ * Writes partner_longitude and partner_latitude of the res.partner model.
+ *
+ * @private
+ * @return {Promise}
+ */
+ _writeCoordinatesUsers: function () {
+ if (this.partnerToCache.length) {
+ this._rpc({
+ model: 'res.partner',
+ method: 'update_latitude_longitude',
+ context: self.context,
+ args: [this.partnerToCache]
+ });
+ this.partnerToCache = [];
+ }
+ },
+});
+
+return MapModel;
+});
diff --git a/odex30_base/odex30_web_map/static/src/js/map_renderer.js b/odex30_base/odex30_web_map/static/src/js/map_renderer.js
new file mode 100644
index 0000000..d7955d9
--- /dev/null
+++ b/odex30_base/odex30_web_map/static/src/js/map_renderer.js
@@ -0,0 +1,463 @@
+odoo.define('odex30_web_map.MapRenderer', function (require) {
+ "use strict";
+
+ const AbstractRendererOwl = require('web.AbstractRendererOwl');
+
+ const { useRef, useState } = owl.hooks;
+
+ const apiTilesRouteWithToken =
+ 'https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}';
+ const apiTilesRouteWithoutToken = 'https://a.tile.openstreetmap.org/{z}/{x}/{y}.png';
+
+ const colors = [
+ '#F06050',
+ '#6CC1ED',
+ '#F7CD1F',
+ '#814968',
+ '#30C381',
+ '#D6145F',
+ '#475577',
+ '#F4A460',
+ '#EB7E7F',
+ '#2C8397',
+ ];
+
+ const mapTileAttribution = `
+ © Mapbox
+ © OpenStreetMap
+
+
+ Improve this map
+
+ `;
+
+ class MapRenderer extends AbstractRendererOwl {
+ /**
+ * @constructor
+ */
+ constructor() {
+ super(...arguments);
+ this.leafletMap = null;
+ this.markers = [];
+ this.polylines = [];
+ this.mapContainerRef = useRef('mapContainer');
+ this.state = useState({
+ closedGroupIds: [],
+ });
+ }
+ /**
+ * Load marker icons.
+ *
+ * @override
+ */
+ async willStart() {
+ const p = { method: 'GET' };
+ [this._pinCircleSVG, this._pinNoCircleSVG] = await Promise.all([
+ this.env.services.httpRequest('odex25_web_map/static/img/pin-circle.svg', p, 'text'),
+ this.env.services.httpRequest('odex25_web_map/static/img/pin-no-circle.svg', p, 'text'),
+ ]);
+ return super.willStart(...arguments);
+ }
+ /**
+ * Initialize and mount map.
+ *
+ * @override
+ */
+ mounted() {
+ this.leafletMap = L.map(this.mapContainerRef.el, {
+ maxBounds: [L.latLng(180, -180), L.latLng(-180, 180)],
+ });
+ L.tileLayer(this.apiTilesRoute, {
+ attribution: mapTileAttribution,
+ tileSize: 512,
+ zoomOffset: -1,
+ minZoom: 2,
+ maxZoom: 19,
+ id: 'mapbox/streets-v11',
+ accessToken: this.props.mapBoxToken,
+ }).addTo(this.leafletMap);
+ this._updateMap();
+ super.mounted(...arguments);
+ }
+ /**
+ * Update position in the map, markers and routes.
+ *
+ * @override
+ */
+ patched() {
+ this._updateMap();
+ super.patched(...arguments);
+ }
+ /**
+ * Update group opened/closed state.
+ *
+ * @override
+ */
+ willUpdateProps(nextProps) {
+ if (this.props.groupBy !== nextProps.groupBy) {
+ this.state.closedGroupIds = [];
+ }
+ return super.willUpdateProps(...arguments);
+ }
+ /**
+ * Remove map and the listeners on its markers and routes.
+ *
+ * @override
+ */
+ willUnmount() {
+ for (const marker of this.markers) {
+ marker.off('click');
+ }
+ for (const polyline of this.polylines) {
+ polyline.off('click');
+ }
+ this.leafletMap.remove();
+ super.willUnmount(...arguments);
+ }
+
+ //----------------------------------------------------------------------
+ // Getters
+ //----------------------------------------------------------------------
+
+ /**
+ * Return the route to the tiles api with or without access token.
+ *
+ * @returns {string}
+ */
+ get apiTilesRoute() {
+ return this.props.mapBoxToken ? apiTilesRouteWithToken : apiTilesRouteWithoutToken;
+ }
+
+ //----------------------------------------------------------------------
+ // Private
+ //----------------------------------------------------------------------
+
+ /**
+ * If there's located records, adds the corresponding marker on the map.
+ * Binds events to the created markers.
+ *
+ * @private
+ */
+ _addMarkers() {
+ this._removeMarkers();
+
+ const markersInfo = {};
+ let records = this.props.records;
+ if (this.props.groupBy) {
+ records = Object.entries(this.props.recordGroups)
+ .filter(([key]) => !this.state.closedGroupIds.includes(key))
+ .flatMap(([, value]) => value.records);
+ }
+
+ for (const record of records) {
+ const partner = record.partner;
+ if (partner && partner.partner_latitude && partner.partner_longitude) {
+ const key = `${partner.partner_latitude}-${partner.partner_longitude}`;
+ if (key in markersInfo) {
+ markersInfo[key].record = record;
+ markersInfo[key].ids.push(record.id);
+ } else {
+ markersInfo[key] = { record: record, ids: [record.id] };
+ }
+ }
+ }
+
+ for (const markerInfo of Object.values(markersInfo)) {
+ const params = {
+ count: markerInfo.ids.length,
+ isMulti: markerInfo.ids.length > 1,
+ number: this.props.records.indexOf(markerInfo.record) + 1,
+ numbering: this.props.numbering,
+ pinSVG: (this.props.numbering ? this._pinNoCircleSVG : this._pinCircleSVG),
+ };
+
+ if (this.props.groupBy) {
+ const group = Object.entries(this.props.recordGroups)
+ .find(([, value]) => value.records.includes(markerInfo.record));
+ params.color = this._getGroupColor(group[0]);
+ }
+
+ // Icon creation
+ const iconInfo = {
+ className: 'o_map_marker',
+ html: this.env.qweb.renderToString('odex25_web_map.marker', params),
+ };
+
+ // Attach marker with icon and popup
+ const marker = L.marker([
+ markerInfo.record.partner.partner_latitude,
+ markerInfo.record.partner.partner_longitude
+ ], { icon: L.divIcon(iconInfo) });
+ marker.addTo(this.leafletMap);
+ marker.on('click', () => {
+ this._createMarkerPopup(markerInfo);
+ });
+ this.markers.push(marker);
+ }
+ }
+ /**
+ * If there are computed routes, create polylines and add them to the map.
+ * each element of this.props.routeInfo[0].legs array represent the route between
+ * two waypoints thus each of these must be a polyline.
+ *
+ * @private
+ */
+ _addRoutes() {
+ this._removeRoutes();
+ if (!this.props.mapBoxToken || !this.props.routeInfo.routes.length) {
+ return;
+ }
+
+ for (const leg of this.props.routeInfo.routes[0].legs) {
+ const latLngs = [];
+ for (const step of leg.steps) {
+ for (const coordinate of step.geometry.coordinates) {
+ latLngs.push(L.latLng(coordinate[1], coordinate[0]));
+ }
+ }
+
+ const polyline = L.polyline(latLngs, {
+ color: 'blue',
+ weight: 5,
+ opacity: 0.3,
+ }).addTo(this.leafletMap);
+
+ const polylines = this.polylines;
+ polyline.on('click', function () {
+ for (const polyline of polylines) {
+ polyline.setStyle({ color: 'blue', opacity: 0.3 });
+ }
+ this.setStyle({ color: 'darkblue', opacity: 1.0 });
+ });
+ this.polylines.push(polyline);
+ }
+ }
+ /**
+ * Create a popup for the specified marker.
+ *
+ * @private
+ * @param {Object} markerInfo
+ */
+ _createMarkerPopup(markerInfo) {
+ const popupFields = this._getMarkerPopupFields(markerInfo);
+ const partner = markerInfo.record.partner;
+ const popupHtml = this.env.qweb.renderToString('odex25_web_map.markerPopup', {
+ fields: popupFields,
+ hasFormView: this.props.hasFormView,
+ url: `https://www.google.com/maps/dir/?api=1&destination=${partner.partner_latitude},${partner.partner_longitude}`,
+ });
+
+ const popup = L.popup({ offset: [0, -30] })
+ .setLatLng([partner.partner_latitude, partner.partner_longitude])
+ .setContent(popupHtml)
+ .openOn(this.leafletMap);
+
+ const openBtn = popup.getElement().querySelector('button.o_open');
+ if (openBtn) {
+ openBtn.onclick = () => {
+ this.trigger('open_clicked', { ids: markerInfo.ids });
+ };
+ }
+ return popup;
+ }
+ /**
+ * @private
+ * @param {Number} groupId
+ */
+ _getGroupColor(groupId) {
+ const index = Object.keys(this.props.recordGroups).indexOf(groupId);
+ return colors[index % colors.length];
+ }
+ /**
+ * Creates an array of latLng objects if there is located records.
+ *
+ * @private
+ * @returns {latLngBounds|boolean} objects containing the coordinates that
+ * allows all the records to be shown on the map or returns false
+ * if the records does not contain any located record.
+ */
+ _getLatLng() {
+ const tabLatLng = [];
+ for (const record of this.props.records) {
+ const partner = record.partner;
+ if (partner && partner.partner_latitude && partner.partner_longitude) {
+ tabLatLng.push(L.latLng(partner.partner_latitude, partner.partner_longitude));
+ }
+ }
+ if (!tabLatLng.length) {
+ return false;
+ }
+ return L.latLngBounds(tabLatLng);
+ }
+ /**
+ * Get the fields' name and value to display in the popup.
+ *
+ * @private
+ * @param {Object} markerInfo
+ * @returns {Object} value contains the value of the field and string
+ * contains the value of the xml's string attribute
+ */
+ _getMarkerPopupFields(markerInfo) {
+ const record = markerInfo.record;
+ const fieldsView = [];
+ // Only display address in multi coordinates marker popup
+ if (markerInfo.ids.length > 1) {
+ if (!this.props.hideAddress) {
+ fieldsView.push({
+ value: record.partner.contact_address_complete,
+ string: this.env._t("Address"),
+ });
+ }
+ return fieldsView;
+ }
+ if (!this.props.hideName) {
+ fieldsView.push({
+ value: record.display_name,
+ string: this.env._t("Name"),
+ });
+ }
+ if (!this.props.hideAddress) {
+ fieldsView.push({
+ value: record.partner.contact_address_complete,
+ string: this.env._t("Address"),
+ });
+ }
+ for (const field of this.props.fieldNamesMarkerPopup) {
+ if (record[field.fieldName]) {
+ const fieldName = record[field.fieldName] instanceof Array ?
+ record[field.fieldName][1] :
+ record[field.fieldName];
+ fieldsView.push({
+ value: fieldName,
+ string: field.string,
+ });
+ }
+ }
+ return fieldsView;
+ }
+ /**
+ * Remove the markers from the map and empty the markers array.
+ *
+ * @private
+ */
+ _removeMarkers() {
+ for (const marker of this.markers) {
+ this.leafletMap.removeLayer(marker);
+ }
+ this.markers = [];
+ }
+ /**
+ * Remove the routes from the map and empty the the polyline array.
+ *
+ * @private
+ */
+ _removeRoutes() {
+ for (const polyline of this.polylines) {
+ this.leafletMap.removeLayer(polyline);
+ }
+ this.polylines = [];
+ }
+ /**
+ * Update position in the map, markers and routes.
+ *
+ * @private
+ */
+ _updateMap() {
+ if (this.props.shouldUpdatePosition) {
+ const initialCoord = this._getLatLng();
+ if (initialCoord) {
+ this.leafletMap.flyToBounds(initialCoord, { animate: false });
+ } else {
+ this.leafletMap.fitWorld();
+ }
+ this.leafletMap.closePopup();
+ }
+ this._addMarkers();
+ this._addRoutes();
+ }
+
+ //----------------------------------------------------------------------
+ // Handlers
+ //----------------------------------------------------------------------
+
+ /**
+ * Center the map on a certain pin and open the popup linked to it.
+ *
+ * @private
+ * @param {Object} record
+ */
+ _centerAndOpenPin(record) {
+ const popup = this._createMarkerPopup({
+ record: record,
+ ids: [record.id],
+ });
+ const px = this.leafletMap.project([record.partner.partner_latitude, record.partner.partner_longitude]);
+ const popupHeight = popup.getElement().offsetHeight;
+ px.y -= popupHeight / 2;
+ const latlng = this.leafletMap.unproject(px);
+ this.leafletMap.panTo(latlng, { animate: true });
+ }
+ /**
+ * @private
+ * @param {Number} id
+ */
+ _toggleGroup(id) {
+ if (this.state.closedGroupIds.includes(id)) {
+ const index = this.state.closedGroupIds.indexOf(id);
+ this.state.closedGroupIds.splice(index, 1);
+ } else {
+ this.state.closedGroupIds.push(id);
+ }
+ }
+ }
+ MapRenderer.props = {
+ arch: Object,
+ count: Number,
+ defaultOrder: {
+ type: String,
+ optional: true,
+ },
+ fetchingCoordinates: Boolean,
+ fieldNamesMarkerPopup: {
+ type: Array,
+ element: {
+ type: Object,
+ shape: {
+ fieldName: String,
+ string: String,
+ },
+ },
+ },
+ groupBy: [String, Boolean],
+ hasFormView: Boolean,
+ hideAddress: Boolean,
+ hideName: Boolean,
+ isEmbedded: Boolean,
+ limit: Number,
+ mapBoxToken: { type: [Boolean, String], optional: 1 },
+ noContentHelp: {
+ type: String,
+ optional: true,
+ },
+ numbering: Boolean,
+ hideTitle: Boolean,
+ panelTitle: String,
+ offset: Number,
+ partners: { type: [Array, Boolean], optional: 1 },
+ recordGroups: Object,
+ records: Array,
+ routeInfo: {
+ type: Object,
+ optional: true,
+ },
+ routing: Boolean,
+ routingError: {
+ type: String,
+ optional: true,
+ },
+ shouldUpdatePosition: Boolean,
+ };
+ MapRenderer.template = 'odex25_web_map.MapRenderer';
+
+ return MapRenderer;
+});
diff --git a/odex30_base/odex30_web_map/static/src/js/map_view.js b/odex30_base/odex30_web_map/static/src/js/map_view.js
new file mode 100644
index 0000000..16ef954
--- /dev/null
+++ b/odex30_base/odex30_web_map/static/src/js/map_view.js
@@ -0,0 +1,87 @@
+odoo.define('odex30_web_map.MapView', function (require) {
+"use strict";
+
+const MapModel = require('odex30_web_map.MapModel');
+const MapController = require('odex30_web_map.MapController');
+const MapRenderer = require('odex30_web_map.MapRenderer');
+const AbstractView = require('web.AbstractView');
+const RendererWrapper = require('web.RendererWrapper');
+const utils = require('web.utils');
+const viewRegistry = require('web.view_registry');
+const _t = require('web.core')._t;
+
+const MapView = AbstractView.extend({
+ jsLibs: [
+ '/odex30_web_map/static/lib/leaflet/leaflet.js',
+ ],
+ config: _.extend({}, AbstractView.prototype.config, {
+ Model: MapModel,
+ Controller: MapController,
+ Renderer: MapRenderer,
+ }),
+ icon: 'fa-map-marker',
+ display_name: 'Map',
+ viewType: 'map',
+ mobile_friendly: true,
+ searchMenuTypes: ['filter', 'groupBy', 'favorite'],
+
+ init: function (viewInfo, params) {
+ this._super.apply(this, arguments);
+
+ const fieldNames = [];
+ const fieldNamesMarkerPopup = [];
+
+ this.loadParams.resPartnerField = this.arch.attrs.res_partner;
+ fieldNames.push(this.arch.attrs.res_partner);
+ fieldNames.push('display_name');
+
+ if (this.arch.attrs.default_order) {
+ this.loadParams.orderBy = [{ name: this.arch.attrs.default_order || 'display_name', asc: true }];
+ }
+
+ const routing = ["true", "True", "1"].includes(this.arch.attrs.routing);
+
+ this.loadParams.limit = this.arch.attrs.limit ?
+ parseInt(this.arch.attrs.limit, 10) :
+ params.limit || 80;
+ this.loadParams.routing = routing;
+ this.rendererParams.routing = routing;
+ this.rendererParams.numbering = this.arch.attrs.routing ? true : false;
+ this.rendererParams.defaultOrder = this.arch.attrs.default_order;
+ this.rendererParams.panelTitle = this.arch.attrs.panel_title || params.displayName || _t('Items');
+ this.rendererParams.hideTitle = utils.toBoolElse(this.arch.attrs.hide_title || '', false);
+
+ const hideName = utils.toBoolElse(this.arch.attrs.hide_name || '', false);
+ this.rendererParams.hideName = hideName;
+ if (!hideName) {
+ fieldNames.push('display_name');
+ }
+ this.rendererParams.hideAddress = utils.toBoolElse(this.arch.attrs.hide_address || '', false);
+
+ this.arch.children.forEach(node => {
+ if (node.tag === 'field') {
+ fieldNames.push(node.attrs.name);
+ fieldNamesMarkerPopup.push({ fieldName: node.attrs.name, string: node.attrs.string });
+ }
+ });
+ this.loadParams.fieldsInfo = this.fields;
+ this.loadParams.fieldNames = _.uniq(fieldNames);
+ this.rendererParams.fieldNamesMarkerPopup = fieldNamesMarkerPopup;
+
+ this.rendererParams.hasFormView = params.actionViews.some(view => view.type === "form");
+
+ this.controllerParams.actionName = params.action ? params.action.name : _t("Untitled");
+ },
+ /**
+ * @override
+ */
+ getRenderer(parent, state) {
+ state = Object.assign({}, state, this.rendererParams);
+ return new RendererWrapper(null, this.config.Renderer, state);
+ },
+});
+
+viewRegistry.add('map', MapView);
+
+return MapView;
+});
diff --git a/odex30_base/odex30_web_map/static/src/scss/map_view.scss b/odex30_base/odex30_web_map/static/src/scss/map_view.scss
new file mode 100644
index 0000000..4cc1d71
--- /dev/null
+++ b/odex30_base/odex30_web_map/static/src/scss/map_view.scss
@@ -0,0 +1,182 @@
+$map-table-row-padding: 25px;
+$map-table-line-padding: 20px;
+$map-number-color: white;
+$map-number-font-size: 19px;
+$map-marker-color: #2c8397;
+.o_map_view {
+ height: 100%;
+
+ .o_map_container {
+ height: 100%;
+
+ .o_map_popup_table {
+ vertical-align: top;
+
+ .contentName {
+ font-weight: bold;
+ white-space: nowrap;
+ line-height: $map-table-row-padding;
+ vertical-align: baseline;
+ }
+
+ .space {
+ padding-left: $map-table-line-padding;
+ }
+
+ .contentString {
+ vertical-align: baseline;
+ }
+ }
+
+ div {
+ .center {
+ display: flex;
+ justify-content: left;
+ align-items: flex-end;
+ margin-top: 8px;
+ }
+
+ .divider {
+ width: 5px;
+ height: auto;
+ display: inline-block;
+ }
+ }
+ }
+
+ .o_pin_list_container {
+ padding: 8px 8px 8px 22px;
+ background-color: white;
+ border-left: 1px solid #dee2e6;
+ height: 100%;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ cursor: default;
+
+ > .o_pin_list_group {
+ margin-bottom: 1rem;
+
+ > .o_pin_list_group_header {
+ display: flex;
+ align-items: baseline;
+ color: #212529;
+
+ svg {
+ height: 1.25rem;
+ margin-right: 0.5rem;
+ }
+
+ > i {
+ margin-right: 1rem;
+ width: 0.5rem;
+ }
+ }
+
+ > .o_pin_list_details {
+ margin-left: 2rem;
+ }
+ }
+
+ .o_pin_list_header {
+ padding: 8px 0;
+ text-transform: uppercase;
+ color: #666666;
+
+ i {
+ color: $o-enterprise-color;
+ margin-right: 0.5rem;
+ }
+
+ span {
+ font-weight: bold;
+ }
+ }
+
+
+ .o_pin_list_details {
+ padding-left: 0px;
+ padding-bottom: 0px;
+ a {
+ color: $gray-900;
+ }
+ > li {
+ list-style-position: inside;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ &.o_pin_located:hover {
+ text-decoration: none;
+ background-color: $o-gray-100;
+ }
+ &:not(.o_pin_located) {
+ cursor: not-allowed;
+ }
+ }
+ }
+
+ ul.o_pin_list_details {
+ list-style: none;
+ cursor: default;
+ padding-bottom: 2px;
+ }
+ }
+
+ //the height and width correspond to the height and width of the custom icon png file
+
+ .o_map_marker {
+ height: 40px !important;
+ width: 30px !important;
+ margin-top: -40px !important;
+ margin-left: -15px !important;
+ color: $map-marker-color;
+ }
+
+ .o_map_marker_badge {
+ @include o-position-absolute($top: -8px, $right: -10px);
+ font-size: 12px;
+ }
+
+ .o_number_icon {
+ position: relative;
+ top: -40px;
+ color: $map-number-color;
+ font-size: $map-number-font-size;
+ text-align: center;
+ margin-top: 10%;
+ }
+
+ .leaflet-fade-anim .leaflet-popup {
+ // used to disabled opening animation for the popups.
+ transition: none;
+ .leaflet-popup-content-wrapper {
+ border-radius: 10px;
+ .leaflet-popup-content {
+ margin: 24px 20px 20px 20px;
+ }
+ }
+ .leaflet-popup-close-button {
+ color: #666666;
+ }
+ }
+
+ .o-map-alert {
+ @include o-position-absolute($top: 0);
+ width: 100%;
+ z-index: 401; // leaflet have 400
+ }
+
+ .leaflet-container a {
+ color: $link-color;
+ &:hover {
+ color: $link-hover-color;
+ }
+ }
+}
+
+/* Fix opw-2124233, preventing rtlcss to reverse the map position */
+.leaflet-pane, .leaflet-tile, .leaflet-marker-icon, .leaflet-marker-shadow,
+.leaflet-tile-container, .leaflet-pane > svg, .leaflet-pane > canvas,
+.leaflet-zoom-box, .leaflet-image-layer, .leaflet-layer {
+ left: 0 #{"/*rtl:ignore*/"};
+ right: auto #{"/*rtl:ignore*/"};
+}
\ No newline at end of file
diff --git a/odex30_base/odex30_web_map/static/src/xml/map.xml b/odex30_base/odex30_web_map/static/src/xml/map.xml
new file mode 100644
index 0000000..1bae249
--- /dev/null
+++ b/odex30_base/odex30_web_map/static/src/xml/map.xml
@@ -0,0 +1,179 @@
+
+
+
+
+
+
+
+
+ Locating new addresses...
+
+
+
+
+
+ To get routing on your map, you first need to setup your Mapbox token.
+
+
+ Set up token
+
+
+ ×
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Unsuccessful routing request:
+
+
+ ×
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/odex30_base/odex30_web_map/static/tests/map_view_tests.js b/odex30_base/odex30_web_map/static/tests/map_view_tests.js
new file mode 100644
index 0000000..7331ff2
--- /dev/null
+++ b/odex30_base/odex30_web_map/static/tests/map_view_tests.js
@@ -0,0 +1,2112 @@
+odoo.define('odex30_web_map.view_view_tests', function (require) {
+"use strict";
+
+const MapView = require('odex30_web_map.MapView');
+const MapModel = require('odex30_web_map.MapModel');
+const testUtils = require('web.test_utils');
+
+const cpHelpers = testUtils.controlPanel;
+const createView = testUtils.createAsyncView;
+
+QUnit.module('mapView', {
+ beforeEach: function () {
+ this.data = {
+ 'project.task': {
+ fields: {
+ display_name: { string: "name", type: "char" },
+ sequence: { string: "sequence", type: 'integer' },
+ partner_id: { string: "partner", type: "many2one", relation: 'res.partner' },
+ another_partner_id: { string: "another relation", type: "many2one", relation: 'res.partner}' },
+ },
+ records: [
+ { id: 1, display_name: "project", partner_id: 1 }
+ ],
+ oneRecord: {
+ records: [
+ { id: 1, display_name: "Foo", partner_id: [1] }
+ ],
+ length: 1
+ },
+
+ twoRecords: {
+ records: [
+ { id: 1, display_name: "FooProject", sequence: 1, partner_id: [1] },
+ { id: 2, display_name: 'BarProject', sequence: 2, partner_id: [2] },
+ ],
+ length: 2
+ },
+
+ threeRecords: {
+ records: [
+ { id: 1, display_name: "FooProject", sequence: 1, partner_id: [1] },
+ { id: 2, display_name: 'BarProject', sequence: 2, partner_id: [2] },
+ { id: 1, display_name: "FooBarProject", sequence: 3, partner_id: [1] }
+ ],
+ length: 3
+ },
+
+ twoRecordOnePartner: {
+ records: [
+ { id: 1, display_name: "FooProject", partner_id: [1] },
+ { id: 2, display_name: 'BarProject', partner_id: [1] },
+ ],
+ length: 2
+ },
+ noRecord: {
+ records: [],
+ length: 0
+ },
+ recordWithouthPartner: {
+ records: [
+ { id: 1, display_name: "Foo", partner_id: [] }
+ ],
+ length: 1
+ },
+ anotherPartnerId: {
+ records: [
+ { id: 1, display_name: "FooProject", another_partner_id: [1] },
+ ],
+ length: 1
+ }
+ },
+
+ 'res.partner': {
+ fields: {
+ name: { string: "Customer", type: "char" },
+ 'partner_latitude': { string: "Latitude", type: "float" },
+ 'partner_longitude': { string: "Longitude", type: "float" },
+ 'contact_address_complete': { string: 'Address', type: "char" },
+ 'task_ids': {
+ string: 'Task',
+ type: "one2many",
+ relation: "project.task",
+ relation_field: "partner_id"
+ },
+ sequence: { string: 'sequence', type: 'integer' }
+ },
+ records: [
+ {
+ id: 1, name: 'Foo', 'partner_latitude': 10.0, 'partner_longitude': 10.5,
+ 'contact_address_complete': 'Chaussée de Namur 40, 1367, Ramillies', sequence: 1
+ },
+ {
+ id: 2, name: 'Foo', 'partner_latitude': 10.0, 'partner_longitude': 10.5,
+ 'contact_address_complete': 'Chaussée de Namur 40, 1367, Ramillies', sequence: 3
+ },
+
+ ],
+ coordinatesNoAddress: [
+ {
+ id: 1, name: 'Foo', 'partner_latitude': 10.0, 'partner_longitude': 10.5
+ }
+ ],
+ oneLocatedRecord: [
+ {
+ id: 1, name: 'Foo', 'partner_latitude': 10.0, 'partner_longitude': 10.5,
+ 'contact_address_complete': 'Chaussée de Namur 40, 1367, Ramillies', sequence: 1
+ },
+ ],
+ wrongCoordinatesNoAddress: [
+ {
+ id: 1, name: 'Foo', 'partner_latitude': 10000.0, 'partner_longitude': 100000.5
+ }
+ ],
+ noCoordinatesGoodAddress: [
+ {
+ id: 1, name: 'Foo', 'partner_latitude': 0, 'partner_longitude': 0,
+ 'contact_address_complete': 'Chaussée de Namur 40, 1367, Ramillies'
+ }
+ ],
+ emptyRecords: [],
+ twoRecordsAddressNoCoordinates:
+ [
+ {
+ id: 2, name: 'Foo',
+ 'contact_address_complete': 'Chaussée de Namur 40, 1367, Ramillies', sequence: 3
+ },
+ {
+ id: 1, name: 'Bar',
+ 'contact_address_complete': 'Chaussée de Louvain 94, 5310 Éghezée', sequence: 1
+ },
+ ],
+ twoRecordsAddressCoordinates:
+ [
+ {
+ id: 2, name: 'Foo', 'partner_latitude': 10.0, 'partner_longitude': 10.5,
+ 'contact_address_complete': 'Chaussée de Namur 40, 1367, Ramillies', sequence: 3
+ },
+ {
+ id: 1, name: 'Bar', 'partner_latitude': 10.0, 'partner_longitude': 10.5,
+ 'contact_address_complete': 'Chaussée de Louvain 94, 5310 Éghezée', sequence: 1
+ },
+ ],
+ twoRecordsOneUnlocated:
+ [
+ {
+ id: 1, name: 'Foo',
+ 'contact_address_complete': 'Chaussée de Namur 40, 1367, Ramillies', sequence: 3
+ },
+ {
+ id: 2, name: 'Bar',
+ },
+ ],
+ unlocatedRecords:
+ [
+ { id: 1, name: 'Foo' },
+ ],
+ noCoordinatesWrongAddress:
+ [
+ {
+ id: 1, name: 'Foo',
+ 'contact_address_complete': 'Cfezfezfefes'
+ }
+ ],
+ }
+ };
+ testUtils.mock.patch(MapModel, {
+ // set delay to 0 as _fetchCoordinatesFromAddressOSM is mocked
+ COORDINATE_FETCH_DELAY: 0,
+ _fetchCoordinatesFromAddressMB: function (record) {
+ if (this.data.mapBoxToken !== 'token') {
+ return Promise.reject({ status: 401 });
+ }
+ const coordinates = [];
+ coordinates[0] = 10.0;
+ coordinates[1] = 10.5;
+ const geometry = { coordinates };
+ const features = [];
+ features[0] = { geometry };
+ const successResponse = { features };
+ const failResponse = { features: [] };
+ switch (record.contact_address_complete) {
+ case 'Cfezfezfefes':
+ return Promise.resolve(failResponse);
+ case '':
+ return Promise.resolve(failResponse);
+ }
+ return Promise.resolve(successResponse);
+ },
+
+ _fetchCoordinatesFromAddressOSM: function (record) {
+ const coordinates = [];
+ coordinates[0] = { lat: 10.0, lon: 10.5 };
+ switch (record.contact_address_complete) {
+ case 'Cfezfezfefes':
+ return Promise.resolve([]);
+ case '':
+ return Promise.resolve([]);
+ }
+ return Promise.resolve(coordinates);
+ },
+
+ _fetchRoute: function () {
+ if (this.data.mapBoxToken !== 'token') {
+ return Promise.reject({ status: 401 });
+ }
+ const legs = [];
+ for (let i = 1; i < this.data.records.length; i++) {
+ const coordinates = [];
+ coordinates[0] = [10, 10.5];
+ coordinates[1] = [10, 10.6];
+ const geometry = { coordinates };
+ const steps = [];
+ steps[0] = { geometry };
+ legs.push({ steps: steps });
+ }
+ const routes = [];
+ routes[0] = { legs };
+ return Promise.resolve({ routes });
+ },
+ _notifyFetchedCoordinate: function () {
+ // do not notify in tests as coords fetching is " synchronous "
+ },
+ _openStreetMapAPI: function () {
+ // return promise to wait for it
+ return this._openStreetMapAPIAsync();
+ },
+ });
+ },
+ afterEach: function () {
+ testUtils.mock.unpatch(MapModel);
+ }
+}, function () {
+
+ //--------------------------------------------------------------------------
+ // Testing data fetching
+ //--------------------------------------------------------------------------
+
+ /**
+ * data: no record
+ * should display a map with the minimum level of zoom
+ * Should have no record
+ * Should have no marker
+ * Should have no route
+ */
+ QUnit.test('Create a view with no record', async function (assert) {
+ assert.expect(8);
+
+ const map = await createView({
+ View: MapView,
+ model: 'project.task',
+ data: this.data,
+ arch:
+ `
+
+ `,
+ mockRPC: function (route, args) {
+ switch (route) {
+ case '/web/dataset/search_read':
+ assert.strictEqual(args.model, 'project.task',
+ 'The model should be project.task');
+ assert.strictEqual(args.fields[0], 'partner_id');
+ assert.strictEqual(args.fields[1], 'display_name');
+ return Promise.resolve(this.data['project.task'].noRecord);
+ case '/web/dataset/call_kw/res.partner/search_read':
+ assert.ok(false,
+ 'Should not search_read the partners if there are no partner');
+ }
+ return Promise.resolve();
+ },
+ session: {
+ map_box_token: 'token'
+ },
+ });
+ assert.strictEqual(map.model.resPartnerField, 'partner_id',
+ 'the resPartnerField should be set');
+
+ assert.strictEqual(map.renderer.props.records.length, 0,
+ 'There should be no records');
+ assert.containsNone(map, 'div.leaflet-marker-icon',
+ 'No marker should be on a the map.');
+ assert.containsNone(map.$('.leaflet-overlay-pane'), 'path',
+ 'No route should be shown');
+ assert.strictEqual(map.renderer.componentRef.comp.leafletMap.getZoom(), 2,
+ 'The map should at its minimum zoom level(2)');
+ map.destroy();
+ });
+
+ /**
+ * data: one record that has no partner linked to it
+ * The record should be kept and displayed in the list of records in gray (no clickable)
+ * should have no marker
+ * Should have no route
+ * Map should be at his minimum zoom level
+ */
+ QUnit.test('Create a view with one record that has no partner', async function (assert) {
+ assert.expect(6);
+
+ const map = await createView({
+ View: MapView,
+ model: 'project.task',
+ data: this.data,
+ arch: ' ',
+ mockRPC: function (route) {
+ switch (route) {
+ case '/web/dataset/search_read':
+ return Promise.resolve(this.data['project.task'].recordWithouthPartner);
+ case '/web/dataset/call_kw/res.partner/search_read':
+ return Promise.resolve(this.data['res.partner'].emptyRecords);
+ }
+ return Promise.resolve();
+ },
+ session: {
+ map_box_token: 'token'
+ },
+ });
+ assert.strictEqual(map.renderer.props.records.length, 1,
+ 'There should be no records');
+ assert.containsNone(map, 'div.leaflet-marker-icon',
+ 'No marker should be on a the map.');
+ assert.containsNone(map.$('.leaflet-overlay-pane'), 'path',
+ 'No route should be shown');
+ assert.strictEqual(map.renderer.componentRef.comp.leafletMap.getZoom(), 2,
+ 'The map should at its minimum level of zoom(2)');
+ assert.containsOnce(map, '.o_pin_list_container .o_pin_list_details li');
+ assert.containsOnce(map, '.o_pin_list_container .o_pin_list_details li span');
+
+ map.destroy();
+ });
+
+ /**
+ * data: one record that has a partner which has coordinates but no address
+ * One record
+ * One marker
+ * no route
+ * Map should not be at his minimum zoom level
+ *
+ */
+ QUnit.test('Create a view with one record and a partner located by coordinates', async function (assert) {
+ assert.expect(3);
+
+ const map = await createView({
+ View: MapView,
+ model: 'project.task',
+ data: this.data,
+ arch: ' ',
+ mockRPC: function (route) {
+ switch (route) {
+ case '/web/dataset/search_read':
+ return Promise.resolve(this.data['project.task'].oneRecord);
+ case '/web/dataset/call_kw/res.partner/search_read':
+ return Promise.resolve(this.data['res.partner'].coordinatesNoAddress);
+ }
+ return Promise.resolve();
+ },
+ session: {
+ map_box_token: 'token'
+ },
+ });
+ assert.strictEqual(map.renderer.props.records.length, 1,
+ 'There should be one records');
+ assert.containsOnce(map, 'div.leaflet-marker-icon',
+ 'There should be one marker on the map');
+ assert.containsNone(map.$('.leaflet-overlay-pane'), 'path',
+ 'There should be no route on the map');
+
+ map.destroy();
+ });
+
+ /**
+ * data: one record linked to one partner with no address and wrong coordinates
+ * api: MapBox
+ * record should be kept and displayed in the list
+ * no route
+ * no marker
+ * map should be at its minimum zoom level
+ */
+ QUnit.test('Create view with one record linked to a partner with wrong coordinates with MB', async function (assert) {
+ assert.expect(5);
+
+ const map = await createView({
+ View: MapView,
+ model: 'project.task',
+ data: this.data,
+ arch: ' ',
+ mockRPC: function (route) {
+ switch (route) {
+ case '/web/dataset/search_read':
+ return Promise.resolve(this.data['project.task'].oneRecord);
+ case '/web/dataset/call_kw/res.partner/search_read':
+ return Promise.resolve(this.data['res.partner'].wrongCoordinatesNoAddress);
+ }
+ return Promise.resolve();
+ },
+ session: {
+ map_box_token: 'token'
+ },
+ });
+ assert.strictEqual(map.renderer.props.records.length, 1, 'There should be one records');
+ assert.containsNone(map, 'div.leaflet-marker-icon',
+ 'There should be np marker on the map');
+ assert.containsNone(map.$('.leaflet-overlay-pane'), 'path',
+ 'There should be no route on the map');
+ assert.containsOnce(map, '.o_pin_list_container .o_pin_list_details li');
+ assert.containsOnce(map, '.o_pin_list_container .o_pin_list_details li span');
+
+ map.destroy();
+ });
+
+ /**
+ * data: one record linked to one partner with no address and wrong coordinates
+ * api: OpenStreet Map
+ * record should be kept
+ * no route
+ * no marker
+ * map should be at its minimum zoom level
+ */
+ QUnit.test('Create view with one record linked to a partner with wrong coordinates with OSM', async function (assert) {
+ assert.expect(3);
+
+ const map = await createView({
+ View: MapView,
+ model: 'project.task',
+ data: this.data,
+ arch: ' ',
+ mockRPC: function (route) {
+ switch (route) {
+ case '/web/dataset/search_read':
+ return Promise.resolve(this.data['project.task'].oneRecord);
+ case '/web/dataset/call_kw/res.partner/search_read':
+ return Promise.resolve(this.data['res.partner'].wrongCoordinatesNoAddress);
+ }
+ return Promise.resolve();
+ },
+ session: {
+ map_box_token: ''
+ },
+ });
+ assert.strictEqual(map.renderer.props.records.length, 1, 'There should be one records');
+ assert.containsNone(map, 'div.leaflet-marker-icon',
+ 'There should be no marker on the map');
+ assert.containsNone(map.$('.leaflet-overlay-pane'), 'path',
+ 'There should be no route on the map');
+
+ map.destroy();
+ });
+ /**
+ * data: one record linked to one partner with no coordinates and good address
+ * api: OpenStreet Map
+ * caching RPC called, assert good args
+ * one record
+ * no route
+ */
+ QUnit.test('Create View with one record linked to a partner with no coordinates and right address OSM', async function (assert) {
+ assert.expect(7);
+
+ const map = await createView({
+ View: MapView,
+ model: 'project.task',
+ data: this.data,
+ arch: ' ',
+ mockRPC: function (route, args) {
+ switch (route) {
+ case '/web/dataset/search_read':
+ return Promise.resolve(this.data['project.task'].oneRecord);
+ case '/web/dataset/call_kw/res.partner/search_read':
+ return Promise.resolve(this.data['res.partner'].noCoordinatesGoodAddress);
+ case '/web/dataset/call_kw/res.partner/update_latitude_longitude':
+ assert.strictEqual(args.model, "res.partner",
+ 'The model should be "res.partner"');
+ assert.strictEqual(args.method, "update_latitude_longitude");
+ assert.strictEqual(args.args[0].length, 1,
+ 'There should be one record needing caching');
+ assert.strictEqual(args.args[0][0].id, 1,
+ 'The records\'s id should be 1');
+ }
+ return Promise.resolve();
+ },
+ session: {
+ map_box_token: ''
+ },
+ });
+ assert.strictEqual(map.renderer.props.records.length, 1,
+ 'There should be one records');
+ assert.containsOnce(map, 'div.leaflet-marker-icon',
+ 'There should be one marker on the map');
+ assert.containsNone(map.$('.leaflet-overlay-pane'), 'path',
+ 'There should be no route on the map');
+
+ map.destroy();
+ });
+
+ /**
+ * data: one record linked to one partner with no coordinates and good address
+ * api: MapBox
+ * caching RPC called, assert good args
+ * one record
+ * no route
+ */
+ QUnit.test('Create View with one record linked to a partner with no coordinates and right address MB', async function (assert) {
+ assert.expect(7);
+
+ const map = await createView({
+ View: MapView,
+ model: 'project.task',
+ data: this.data,
+ arch: ' ',
+ mockRPC: function (route, args) {
+ switch (route) {
+ case '/web/dataset/search_read':
+ return Promise.resolve(this.data['project.task'].oneRecord);
+ case '/web/dataset/call_kw/res.partner/search_read':
+ return Promise.resolve(this.data['res.partner'].noCoordinatesGoodAddress);
+ case '/web/dataset/call_kw/res.partner/update_latitude_longitude':
+ assert.strictEqual(args.model, "res.partner",
+ 'The model should be "res.partner"');
+ assert.strictEqual(args.method, "update_latitude_longitude");
+ assert.strictEqual(args.args[0].length, 1,
+ 'There should be one record needing caching');
+ assert.strictEqual(args.args[0][0].id, 1,
+ 'The records\'s id should be 1');
+ }
+ return Promise.resolve();
+ },
+ session: {
+ map_box_token: 'token'
+ },
+ });
+ assert.strictEqual(map.renderer.props.records.length, 1,
+ 'There should be one records');
+ assert.containsOnce(map, 'div.leaflet-marker-icon',
+ 'There should be one marker on the map');
+ assert.containsNone(map.$('.leaflet-overlay-pane'), 'path',
+ 'There should be no route on the map');
+
+ map.destroy();
+ });
+
+ /**
+ * data: one record linked to a partner with no coordinates and no address
+ * api: MapBox
+ * 1 record
+ * no route
+ * no marker
+ * min level of zoom
+ */
+ QUnit.test('Create view with no located record', async function (assert) {
+ assert.expect(4);
+
+ const map = await createView({
+ View: MapView,
+ model: 'project.task',
+ data: this.data,
+ arch: ' ',
+ mockRPC: function (route) {
+ switch (route) {
+ case '/web/dataset/search_read':
+ return Promise.resolve(this.data['project.task'].oneRecord);
+ case '/web/dataset/call_kw/res.partner/search_read':
+ return Promise.resolve(this.data['res.partner'].unlocatedRecords);
+ }
+ return Promise.resolve();
+ },
+ session: {
+ map_box_token: 'token'
+ }
+ });
+ assert.strictEqual(map.renderer.props.records.length, 1,
+ 'There should be one records');
+ assert.containsNone(map, 'div.leaflet-marker-icon',
+ 'No marker should be on a the map.');
+ assert.containsNone(map.$('.leaflet-overlay-pane'), 'path',
+ 'No route should be shown');
+ assert.strictEqual(map.renderer.componentRef.comp.leafletMap.getZoom(), 2,
+ 'The map should at its minimum zoom level(2)');
+
+ map.destroy();
+ });
+
+ /**
+ * data: one record linked to a partner with no coordinates and no address
+ * api: OSM
+ * one record
+ * no route
+ * no marker
+ * min level of zoom
+ */
+ QUnit.test('Create view with no located record OSM', async function (assert) {
+ assert.expect(4);
+
+ const map = await createView({
+ View: MapView,
+ model: 'project.task',
+ data: this.data,
+ arch: ' ',
+ mockRPC: function (route) {
+ switch (route) {
+ case '/web/dataset/search_read':
+ return Promise.resolve(this.data['project.task'].oneRecord);
+ case '/web/dataset/call_kw/res.partner/search_read':
+ return Promise.resolve(this.data['res.partner'].unlocatedRecords);
+ }
+ return Promise.resolve();
+ },
+ session: {
+ map_box_token: ''
+ }
+ });
+ assert.strictEqual(map.renderer.props.records.length, 1,
+ 'There should be one records');
+ assert.containsNone(map, 'div.leaflet-marker-icon',
+ 'No marker should be on a the map.');
+ assert.containsNone(map.$('.leaflet-overlay-pane'), 'path',
+ 'No route should be shown');
+ assert.strictEqual(map.renderer.componentRef.comp.leafletMap.getZoom(), 2,
+ 'The map should at its minimum zoom level(2)');
+
+ map.destroy();
+ });
+
+ /**
+ * data: one record linked to a partner with no coordinates and wrong address
+ * api: OSM
+ * one record
+ * no route
+ * no marker
+ * min level zoom
+ */
+ QUnit.test('Create view with no badly located record OSM', async function (assert) {
+ assert.expect(4);
+
+ const map = await createView({
+ View: MapView,
+ model: 'project.task',
+ data: this.data,
+ arch: ' ',
+ mockRPC: function (route) {
+ switch (route) {
+ case '/web/dataset/search_read':
+ return Promise.resolve(this.data['project.task'].oneRecord);
+ case '/web/dataset/call_kw/res.partner/search_read':
+ return Promise.resolve(this.data['res.partner'].noCoordinatesWrongAddress);
+ }
+ return Promise.resolve();
+ },
+ session: {
+ map_box_token: ''
+ }
+ });
+ assert.strictEqual(map.renderer.props.records.length, 1,
+ 'There should be one records');
+ assert.containsNone(map, 'div.leaflet-marker-icon',
+ 'No marker should be on a the map.');
+ assert.containsNone(map.$('.leaflet-overlay-pane'), 'path',
+ 'No route should be shown');
+ assert.strictEqual(map.renderer.componentRef.comp.leafletMap.getZoom(), 2,
+ 'The map should at its minimum zoom level(2)');
+
+ map.destroy();
+ });
+
+ /**
+ * data: one record linked to a partner with no coordinates and wrong address
+ * api: mapbox
+ * one record
+ * no route
+ * no marker
+ * min level zoom
+ */
+
+ QUnit.test('Create view with no badly located record MB', async function (assert) {
+ assert.expect(4);
+
+ const map = await createView({
+ View: MapView,
+ model: 'project.task',
+ data: this.data,
+ arch: ' ',
+ mockRPC: function (route) {
+ switch (route) {
+ case '/web/dataset/search_read':
+ return Promise.resolve(this.data['project.task'].oneRecord);
+ case '/web/dataset/call_kw/res.partner/search_read':
+ return Promise.resolve(this.data['res.partner'].noCoordinatesWrongAddress);
+ }
+ return Promise.resolve();
+ },
+ session: {
+ map_box_token: 'token'
+ }
+ });
+ assert.strictEqual(map.renderer.props.records.length, 1,
+ 'There should be one records');
+ assert.containsNone(map, 'div.leaflet-marker-icon',
+ 'No marker should be on a the map.');
+ assert.containsNone(map.$('.leaflet-overlay-pane'), 'path',
+ 'No route should be shown');
+ assert.strictEqual(map.renderer.componentRef.comp.leafletMap.getZoom(), 2,
+ 'The map should at its minimum zoom level(2)');
+
+ map.destroy();
+ });
+
+ /**
+ * data: 2 records linked to the same partner
+ * 2 records
+ * 2 markers
+ * no route
+ * same partner object
+ * 1 caching request
+ */
+ QUnit.test('Create a view with two located records same partner', async function (assert) {
+ assert.expect(4);
+
+ const map = await createView({
+ View: MapView,
+ model: 'project.task',
+ data: this.data,
+ arch: ' ',
+ mockRPC: function (route) {
+ switch (route) {
+ case '/web/dataset/search_read':
+ return Promise.resolve(this.data['project.task'].twoRecordOnePartner);
+ case '/web/dataset/call_kw/res.partner/search_read':
+ return Promise.resolve(this.data['res.partner'].oneLocatedRecord);
+ }
+ return Promise.resolve();
+ },
+ session: {
+ map_box_token: 'token'
+ },
+ });
+ assert.strictEqual(map.renderer.props.records.length, 2,
+ 'There should be no records');
+ assert.strictEqual(map.$('div.leaflet-marker-icon .o_map_marker_badge').text(), '2',
+ 'There should be a marker for two records');
+ assert.containsOnce(map.$('.leaflet-overlay-pane'), 'path',
+ 'There should be one route showing');
+ assert.equal(map.renderer.props.records[0].partner, map.renderer.props.records[1].partner,
+ 'The records should have the same partner object as a property');
+
+ map.destroy();
+ });
+
+ /**
+ * data: 2 records linked to differnet partners
+ * 2 records
+ * 1 route
+ * different partner object.
+ * 2 caching
+ */
+ QUnit.test('Create a a view with two located records different partner', async function (assert) {
+ assert.expect(5);
+
+ const map = await createView({
+ View: MapView,
+ model: 'project.task',
+ data: this.data,
+ arch: ' ',
+ mockRPC: function (route, args) {
+ switch (route) {
+ case '/web/dataset/search_read':
+ return Promise.resolve(this.data['project.task'].twoRecords);
+ case '/web/dataset/call_kw/res.partner/search_read':
+ return Promise.resolve(this.data['res.partner'].twoRecordsAddressNoCoordinates);
+ case '/web/dataset/call_kw/res.partner/update_latitude_longitude':
+ assert.strictEqual(args.args[0].length, 2,
+ 'Should have 2 record needing caching');
+ }
+ return Promise.resolve();
+ },
+ session: {
+ map_box_token: 'token'
+ },
+ });
+ assert.strictEqual(map.renderer.props.records.length, 2,
+ 'There should be no records');
+ assert.strictEqual(map.$('div.leaflet-marker-icon .o_map_marker_badge').text(), '2',
+ 'There should be a marker for two records');
+ assert.containsOnce(map.$('.leaflet-overlay-pane'), 'path',
+ 'There should be one route showing');
+ assert.notEqual(map.renderer.props.records[0].partner, map.renderer.props.records[1].partner,
+ 'The records should have the same partner object as a property');
+
+ map.destroy();
+ });
+
+ /**
+ * data: 2 valid res.partner records
+ * test the case where the model is res.partner and the "res.partner" field is the id
+ * should have 2 records,
+ * 2 markers
+ * no route
+ */
+ QUnit.test('Create a view with res.partner', async function (assert) {
+ assert.expect(8);
+
+ this.data['res.partner'].recordsPrimary = {
+ records: [
+ {
+ id: 2, name: 'Foo',
+ 'contact_address_complete': 'Chaussée de Namur 40, 1367, Ramillies', sequence: 3
+ },
+ {
+ id: 1, name: 'FooBar',
+ 'contact_address_complete': 'Chaussée de Louvain 94, 5310 Éghezée', sequence: 1
+ }
+ ], length: 2
+ };
+ const map = await createView({
+ View: MapView,
+ model: 'res.partner',
+ data: this.data,
+ arch: ' ',
+ mockRPC: function (route, args) {
+ switch (route) {
+ case '/web/dataset/search_read':
+ assert.strictEqual(args.model, 'res.partner',
+ 'The model should be res.partner');
+ assert.strictEqual(args.fields[0], 'id');
+ return Promise.resolve(this.data['res.partner'].recordsPrimary);
+ case '/web/dataset/call_kw/res.partner/search_read':
+ assert.strictEqual(args.model, 'res.partner',
+ 'The model should be res.partner as well');
+ assert.strictEqual(args.kwargs.domain[1][2][0], 2);
+ assert.strictEqual(args.kwargs.domain[1][2][1], 1);
+ return Promise.resolve(this.data['res.partner'].twoRecordsAddressNoCoordinates);
+ }
+ return Promise.resolve();
+ },
+ session: {
+ map_box_token: 'token'
+ },
+ });
+ assert.strictEqual(map.renderer.props.records.length, 2,
+ 'There should be two records');
+ assert.strictEqual(map.$('div.leaflet-marker-icon .o_map_marker_badge').text(), '2',
+ 'There should be a marker for two records');
+ assert.containsNone(map.$('.leaflet-overlay-pane'), 'path',
+ 'There should be no route showing');
+
+ map.destroy();
+ });
+
+ /**
+ * data: 3 records linked to one located partner and one unlocated
+ * test if only the 2 located records are displayed
+ */
+ QUnit.test('Create a view with 2 located records and 1 unlocated', async function (assert) {
+ assert.expect(4);
+
+ const map = await createView({
+ View: MapView,
+ model: 'project.task',
+ data: this.data,
+ arch: ' ',
+ mockRPC: function (route) {
+ switch (route) {
+ case '/web/dataset/search_read':
+ return Promise.resolve(this.data['project.task'].threeRecords);
+ case '/web/dataset/call_kw/res.partner/search_read':
+ return Promise.resolve(this.data['res.partner'].twoRecordsOneUnlocated);
+ }
+ return Promise.resolve();
+ },
+ session: {
+ map_box_token: 'token'
+ },
+ });
+ assert.strictEqual(map.renderer.props.records.length, 3);
+ assert.strictEqual(map.renderer.props.records[0].partner.id, 1,
+ "The partner's id should be 1");
+ assert.strictEqual(map.renderer.props.records[1].partner.id, 2,
+ "The partner's id should be 2");
+ assert.strictEqual(map.renderer.props.records[2].partner.id, 1,
+ "The partner's id should be 1");
+
+ map.destroy();
+ });
+
+ QUnit.test('Change load limit', async function (assert) {
+ assert.expect(2);
+
+ this.data['project.task'].records = this.data['project.task'].threeRecords.records;
+ this.data['res.partner'].records = this.data['res.partner'].twoRecordsAddressCoordinates;
+ const map = await createView({
+ View: MapView,
+ model: 'project.task',
+ data: this.data,
+ arch: ' ',
+ session: {
+ map_box_token: 'token'
+ },
+ });
+
+ assert.strictEqual(cpHelpers.getPagerValue(map), '1-2');
+ assert.strictEqual(cpHelpers.getPagerSize(map), '3');
+
+ map.destroy();
+ });
+
+ //--------------------------------------------------------------------------
+ // Renderer testing
+ //--------------------------------------------------------------------------
+
+ QUnit.test('Google Maps redirection', async function (assert) {
+ assert.expect(2);
+
+ const map = await createView({
+ View: MapView,
+ model: 'project.task',
+ data: this.data,
+ arch: ' ',
+ mockRPC: function (route) {
+ switch (route) {
+ case '/web/dataset/search_read':
+ return Promise.resolve(this.data['project.task'].twoRecords);
+ case '/web/dataset/call_kw/res.partner/search_read':
+ return Promise.resolve(this.data['res.partner'].twoRecordsAddressNoCoordinates);
+ }
+ return Promise.resolve();
+ },
+ session: {
+ map_box_token: 'token'
+ },
+ });
+ assert.strictEqual(map.$('a.btn.btn-primary').attr('href'),
+ 'https://www.google.com/maps/dir/?api=1&waypoints=10.5,10',
+ 'The link\'s URL should contain the right sets of coordinates');
+
+ await testUtils.dom.click(map.$('.leaflet-marker-icon'));
+ assert.strictEqual(map.$('div.leaflet-popup').find('a.btn.btn-primary').attr('href'),
+ 'https://www.google.com/maps/dir/?api=1&destination=10.5,10',
+ 'The link\'s URL should the right set of coordinates');
+
+ map.destroy();
+ });
+
+ QUnit.test('Unicity of coordinates in Google Maps url', async function(assert){
+ assert.expect(2);
+ var map = await createView({
+ View: MapView,
+ model: 'project.task',
+ data: this.data,
+ arch: '' +
+ ' ',
+ mockRPC: function (route) {
+ switch (route) {
+ case '/web/dataset/search_read':
+ return Promise.resolve(this.data['project.task'].twoRecordOnePartner);
+ case '/web/dataset/call_kw/res.partner/search_read':
+ return Promise.resolve(this.data['res.partner'].twoRecordsAddressNoCoordinates);
+ }
+ return Promise.resolve();
+ },
+ session: {
+ map_box_token: 'token'
+ },
+ });
+
+ assert.strictEqual(map.$('a.btn.btn-primary').attr('href'), 'https://www.google.com/maps/dir/?api=1&waypoints=10.5,10', 'The link\'s URL should contain unqiue sets of coordinates');
+ await testUtils.dom.click(map.$('.leaflet-marker-icon'));
+ assert.strictEqual(map.$('div.leaflet-popup').find('a.btn.btn-primary').attr('href'), 'https://www.google.com/maps/dir/?api=1&destination=10.5,10', 'The link\'s URL should only contain unqiue sets of coordinates');
+ map.destroy();
+ });
+
+ QUnit.test('testing the size of the map', async function (assert) {
+ assert.expect(1);
+
+ const map = await createView({
+ View: MapView,
+ model: 'project.task',
+ data: this.data,
+ arch: ' ',
+ mockRPC: function () {
+ return Promise.resolve();
+ },
+ session: {
+ map_box_token: ''
+ },
+ });
+
+ assert.strictEqual($('.o_map_container').height(), $('.o_content').height(),
+ 'The map should be the same height as the content div');
+ map.destroy();
+ });
+
+ QUnit.test('test the position of pin', async function (assert) {
+ assert.expect(4);
+
+ const map = await createView({
+ View: MapView,
+ model: 'project.task',
+ data: this.data,
+ arch: ' ',
+ mockRPC: function (route) {
+ switch (route) {
+ case '/web/dataset/search_read':
+ return Promise.resolve(this.data['project.task'].twoRecords);
+ case '/web/dataset/call_kw/res.partner/search_read':
+ return Promise.resolve(this.data['res.partner'].twoRecordsAddressNoCoordinates);
+ }
+ return Promise.resolve();
+ },
+ session: {
+ map_box_token: ''
+ },
+ });
+
+ const renderer = map.renderer.componentRef.comp;
+ assert.strictEqual(renderer.markers.length, 1,
+ 'Should have one marker created');
+ assert.strictEqual(map.$('div.leaflet-marker-icon .o_map_marker_badge').text(), '2',
+ 'There should be a marker for two records');
+ assert.strictEqual(renderer.markers[0].getLatLng().lat, 10,
+ 'The latitude should be the same as the record');
+ assert.strictEqual(renderer.markers[0].getLatLng().lng, 10.5,
+ 'The longitude should be the same as the record');
+
+ map.destroy();
+ });
+
+ /**
+ * data: two located records
+ * Create an empty map
+ */
+ QUnit.test('Create of a empty map', async function (assert) {
+ assert.expect(9);
+
+ const map = await createView({
+ View: MapView,
+ model: 'res.partner',
+ data: this.data,
+ arch: ' ',
+ mockRPC: function (route) {
+ switch (route) {
+ case '/web/dataset/search_read':
+ return Promise.resolve(this.data['project.task'].twoRecords);
+ case '/web/dataset/call_kw/res.partner/search_read':
+ return Promise.resolve(this.data['res.partner'].twoRecordsAddressNoCoordinates);
+ }
+ return Promise.resolve();
+ },
+ session: {
+ map_box_token: ''
+ }
+ });
+ const renderer = map.renderer.componentRef.comp;
+ assert.notOk(map.model.resPartnerField, 'the resPartnerField should not be set');
+
+ assert.containsOnce(map, '.o_map_view',
+ '1 div should have the class "o_map_view"');
+ assert.containsOnce(map, '.leaflet-map-pane',
+ "If the map exists this div should exist");
+ assert.ok(renderer.leafletMap,
+ 'If the map exists this property should be initialized');
+ assert.ok($('.leaflet-pane .leaflet-tile-pane').children().length,
+ 'The map tiles should have been happened to the DOM');
+ // if element o_map_container has class leaflet-container then
+ // the map is mounted
+ assert.hasClass(map.el.querySelector('.o_map_container'),
+ 'leaflet-container', 'the map should be in the DOM');
+
+ assert.strictEqual(renderer.polylines.length, 0,
+ 'Should have no polylines');
+ assert.strictEqual($('.leaflet-overlay-pane').children().length, 0,
+ 'Should have no showing route');
+ assert.strictEqual(renderer.leafletMap.getZoom(), 2,
+ 'The level of zoom should should be at it\'s minimum');
+
+ map.destroy();
+ });
+
+ /**
+ * two located records
+ * without routing or default_order
+ * normal marker icon
+ * test the click on them
+ */
+
+ QUnit.test('Create view with normal marker icons', async function (assert) {
+ assert.expect(6);
+
+ const map = await createView({
+ View: MapView,
+ model: 'project.task',
+ data: this.data,
+ arch: ' ',
+ mockRPC: function (route) {
+ switch (route) {
+ case '/web/dataset/search_read':
+ return Promise.resolve(this.data['project.task'].twoRecords);
+ case '/web/dataset/call_kw/res.partner/search_read':
+ return Promise.resolve(this.data['res.partner'].twoRecordsAddressNoCoordinates);
+ }
+ return Promise.resolve();
+ },
+ session: {
+ map_box_token: 'token'
+ },
+ });
+ assert.notOk(map.renderer.props.numbering,
+ 'the numbering option should not be enabled');
+ assert.notOk(map.model.routing,
+ 'The routing option should not be enabled');
+
+ assert.containsOnce(map, '.leaflet-marker-icon',
+ 'There should be 1 marker');
+ assert.containsNone(map.$('.leaflet-overlay-pane'), 'path',
+ 'There should be no route showing');
+
+ await testUtils.dom.click(map.$('.leaflet-marker-icon'));
+
+ assert.strictEqual(map.$('.leaflet-popup-pane').children().length, 1,
+ 'Should have one showing popup');
+
+ await testUtils.dom.click(map.$('div.leaflet-container'));
+
+ assert.notOk(map.renderer.componentRef.comp.markers[0].isPopupOpen(),
+ 'The marker\'s popup should be close');
+
+ map.destroy();
+ });
+
+ /**
+ * two located records
+ * with default_order
+ * no numbered icon
+ * test click on them
+ * asserts that the rpc receive the right parameters
+ */
+ QUnit.test('Create a view with default_order', async function (assert) {
+ assert.expect(7);
+
+ const map = await createView({
+ View: MapView,
+ model: 'project.task',
+ data: this.data,
+ arch: ' ',
+ mockRPC: function (route, args) {
+ switch (route) {
+ case '/web/dataset/search_read':
+ assert.strictEqual(args.sort, 'name ASC',
+ 'The sorting order should be on the field name in a ascendant way');
+ return Promise.resolve(this.data['project.task'].twoRecords);
+ case '/web/dataset/call_kw/res.partner/search_read':
+ return Promise.resolve(this.data['res.partner'].twoRecordsAddressNoCoordinates);
+ }
+ return Promise.resolve();
+ },
+ session: {
+ map_box_token: ''
+ },
+ });
+ assert.ok(map.renderer.props.numbering === false,
+ 'the numbering option should not be enabled');
+ assert.notOk(map.model.routing,
+ 'The routing option should not be enabled');
+ assert.containsOnce(map, 'div.leaflet-marker-icon',
+ 'There should be 1 marker');
+ assert.strictEqual(map.$('div.leaflet-marker-icon .o_map_marker_badge').text(), '2',
+ 'There should be a marker for two records');
+ assert.strictEqual(map.$('.leaflet-popup-pane').children().length, 0,
+ 'Should have no showing popup');
+ await testUtils.dom.click(map.$('div.leaflet-marker-icon'));
+ assert.strictEqual(map.$('.leaflet-popup-pane').children().length, 1,
+ 'Should have one showing popup');
+
+ map.destroy();
+ });
+
+ /**
+ * two locted records
+ * with routing enabled
+ * numbered icon
+ * test click on route
+ */
+ QUnit.test('Create a view with routing', async function (assert) {
+ assert.expect(9);
+
+ const map = await createView({
+ View: MapView,
+ model: 'project.task',
+ data: this.data,
+ arch: ' ',
+ mockRPC: function (route) {
+ switch (route) {
+ case '/web/dataset/search_read':
+ return Promise.resolve(this.data['project.task'].twoRecords);
+ case '/web/dataset/call_kw/res.partner/search_read':
+ return Promise.resolve(this.data['res.partner'].twoRecordsAddressNoCoordinates);
+ }
+ return Promise.resolve();
+ },
+ session: {
+ map_box_token: 'token'
+ },
+ });
+ assert.ok(map.renderer.props.numbering,
+ 'The numbering option should be enabled');
+ assert.ok(map.model.routing,
+ 'The routing option should be enabled');
+
+ assert.strictEqual(map.model.numberOfLocatedRecords, 2,
+ 'Should have 2 located Records');
+ assert.strictEqual(map.renderer.props.routeInfo.routes.length, 1,
+ 'Should have 1 computed route');
+ assert.strictEqual(map.$('div.leaflet-marker-icon .o_map_marker_badge').text(), '2',
+ 'There should be a marker for two records');
+ assert.strictEqual(map.$('path.leaflet-interactive').attr('stroke'), 'blue',
+ 'The route should be blue if it has not been clicked');
+ assert.strictEqual(map.$('path.leaflet-interactive').attr('stroke-opacity'), '0.3',
+ 'The opacity of the polyline should be 0.3');
+ map.renderer.componentRef.comp.polylines[0].fire('click');
+ assert.strictEqual(map.$('path.leaflet-interactive').attr('stroke'), 'darkblue',
+ 'The route should be darkblue after being clicked');
+ assert.strictEqual(map.$('path.leaflet-interactive').attr('stroke-opacity'), '1',
+ 'The opacity of the polyline should be 1');
+
+ map.destroy();
+ });
+
+ QUnit.test('Create a view with routingError', async function (assert) {
+ assert.expect(1);
+
+ testUtils.mock.unpatch(MapModel);
+ testUtils.mock.patch(MapModel, {
+ _maxBoxAPI() {
+ this.data.routingError = "this is test warning";
+ this.data.routeInfo = { routes: [] };
+ return Promise.resolve();
+ }
+ });
+
+ const map = await createView({
+ View: MapView,
+ model: 'project.task',
+ data: this.data,
+ arch: ' ',
+ mockRPC: function (route) {
+ switch (route) {
+ case '/web/dataset/search_read':
+ return Promise.resolve(this.data['project.task'].twoRecords);
+ case '/web/dataset/call_kw/res.partner/search_read':
+ return Promise.resolve([]);
+ }
+ return Promise.resolve();
+ },
+ session: {
+ map_box_token: 'token'
+ },
+ });
+
+ assert.containsOnce(map, '.o_map_view > .o-map-alert',
+ 'should have alert');
+
+ map.destroy();
+ });
+
+ /**
+ * routing with token and one located record
+ * No route
+ */
+ QUnit.test('create a view with routing and one located record', async function (assert) {
+ assert.expect(2);
+
+ const map = await createView({
+ View: MapView,
+ model: 'project.task',
+ data: this.data,
+ arch: ' ',
+ mockRPC: function (route) {
+ switch (route) {
+ case '/web/dataset/search_read':
+ return Promise.resolve(this.data['project.task'].oneRecord);
+ case '/web/dataset/call_kw/res.partner/search_read':
+ return Promise.resolve(this.data['res.partner'].oneLocatedRecord);
+ }
+ return Promise.resolve();
+ },
+ session: {
+ map_box_token: 'token'
+ },
+ });
+ assert.ok(map.model.routing,
+ 'The routing option should be enabled');
+ assert.strictEqual(map.renderer.props.routeInfo.routes.length, 0,
+ 'Should have no computed route');
+
+ map.destroy();
+ });
+
+ /**
+ * no mapbox token
+ * assert that the view uses the right api and routes
+ */
+ QUnit.test('CreateView with empty mapbox token setting', async function (assert) {
+ assert.expect(3);
+ const map = await createView({
+ View: MapView,
+ model: 'project.task',
+ data: this.data,
+ arch: ' ',
+ mockRPC: function (route) {
+ switch (route) {
+ case '/web/dataset/search_read':
+ return Promise.resolve(this.data['project.task'].recordWithouthPartner);
+ case '/web/dataset/call_kw/res.partner/search_read':
+ return Promise.resolve(this.data['res.partner'].emptyRecords);
+ }
+ return Promise.resolve();
+ },
+ session: {
+ map_box_token: ''
+ },
+ });
+ assert.strictEqual(map.model.data.mapBoxToken, '',
+ 'The token should be an empty string');
+ assert.strictEqual(map.renderer.componentRef.comp.apiTilesRoute,
+ 'https://a.tile.openstreetmap.org/{z}/{x}/{y}.png',
+ 'With no token the route for fetching tiles should be "https://a.tile.openstreetmap.org/{z}/{x}/{y}.png"');
+ assert.strictEqual(map.renderer.props.mapBoxToken, '',
+ 'The token should be an empty string');
+
+ map.destroy();
+ });
+
+ /**
+ * wrong mapbox token
+ * assert that the view uses the openstreetmap api
+ */
+ QUnit.test('Create a view with wrong map box setting', async function (assert) {
+ assert.expect(3);
+
+ const map = await createView({
+ View: MapView,
+ model: 'project.task',
+ data: this.data,
+ arch: ' ',
+ mockRPC: function (route) {
+ switch (route) {
+ case '/web/dataset/search_read':
+ return Promise.resolve(this.data['project.task'].twoRecords);
+ case '/web/dataset/call_kw/res.partner/search_read':
+ return Promise.resolve(this.data['res.partner'].twoRecordsAddressNoCoordinates);
+ }
+ return Promise.resolve();
+ },
+ session: {
+ map_box_token: 'vrve'
+ },
+ });
+ assert.strictEqual(map.model.data.mapBoxToken, '',
+ 'The token should be an empty string');
+ assert.strictEqual(map.renderer.componentRef.comp.apiTilesRoute,
+ 'https://a.tile.openstreetmap.org/{z}/{x}/{y}.png',
+ 'With no token the route for fetching tiles should be "https://a.tile.openstreetmap.org/{z}/{x}/{y}.png"');
+ assert.strictEqual(map.renderer.props.mapBoxToken, '',
+ 'The token should be an empty string');
+
+ map.destroy();
+ });
+
+ /**
+ * wrong mapbox token fails at catch at route computing
+ */
+ QUnit.test('create a view with wrong map box setting and located records', async function (assert) {
+ assert.expect(3);
+
+ const map = await createView({
+ View: MapView,
+ model: 'project.task',
+ data: this.data,
+ arch: ' ',
+ mockRPC: function (route) {
+ switch (route) {
+ case '/web/dataset/search_read':
+ return Promise.resolve(this.data['project.task'].twoRecords);
+ case '/web/dataset/call_kw/res.partner/search_read':
+ return Promise.resolve(this.data['res.partner'].twoRecordsAddressCoordinates);
+ }
+ return Promise.resolve();
+ },
+ session: {
+ map_box_token: 'frezfre'
+ },
+ });
+ assert.strictEqual(map.model.data.mapBoxToken, '',
+ 'The token should be an empty string');
+ assert.strictEqual(map.renderer.componentRef.comp.apiTilesRoute,
+ 'https://a.tile.openstreetmap.org/{z}/{x}/{y}.png',
+ 'With no token the route for fetching tiles should be "https://a.tile.openstreetmap.org/{z}/{x}/{y}.png"');
+ assert.strictEqual(map.renderer.props.mapBoxToken, '',
+ 'The token should be an empty string');
+
+ map.destroy();
+ });
+
+ /**
+ * create view with right map box token
+ * assert that the view uses the map box api
+ */
+ QUnit.test('Create a view with the right map box token', async function (assert) {
+ assert.expect(3);
+
+ const map = await createView({
+ View: MapView,
+ model: 'project.task',
+ data: this.data,
+ arch: ' ',
+ mockRPC: function (route) {
+ switch (route) {
+ case '/web/dataset/search_read':
+ return Promise.resolve(this.data['project.task'].recordWithouthPartner);
+ case '/web/dataset/call_kw/res.partner/search_read':
+ return Promise.resolve(this.data['res.partner'].emptyRecords);
+ }
+ return Promise.resolve();
+ },
+ session: {
+ map_box_token: 'token'
+ },
+ });
+ assert.strictEqual(map.model.data.mapBoxToken, 'token',
+ 'The token should be the right token');
+ assert.strictEqual(map.renderer.componentRef.comp.apiTilesRoute,
+ 'https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}',
+ 'With no token the route for fetching tiles should be "https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}"');
+ assert.strictEqual(map.renderer.props.mapBoxToken, 'token',
+ 'The token should be the right token');
+
+ map.destroy();
+ });
+
+ /**
+ * data: two located records
+ */
+ QUnit.test('Click on pin shows popup, click on another shuts the first and open the other', async function (assert) {
+ assert.expect(3);
+
+ const map = await createView({
+ View: MapView,
+ model: 'project.task',
+ data: this.data,
+ arch: ' ',
+ mockRPC: function (route) {
+ switch (route) {
+ case '/web/dataset/search_read':
+ return Promise.resolve(this.data['project.task'].twoRecords);
+ case '/web/dataset/call_kw/res.partner/search_read':
+ return Promise.resolve(this.data['res.partner'].twoRecordsAddressNoCoordinates);
+ }
+ return Promise.resolve();
+ },
+ session: {
+ map_box_token: 'token'
+ },
+ });
+ assert.notOk(map.$('.leaflet-pane .leaflet-popup-pane').children().length,
+ 'The popup div should be empty');
+
+ await testUtils.dom.click(map.$('div.leaflet-marker-icon'));
+ assert.strictEqual(map.$('.leaflet-popup-pane').children().length, 1,
+ 'The popup div should contain one element');
+
+ await testUtils.dom.click(map.$el.find('.leaflet-map-pane'));
+ // wait for the popup's destruction which takes a certain time...
+ for (let i = 0; i < 15; i++) {
+ await testUtils.nextTick();
+ }
+ assert.notOk(map.$('.leaflet-pane .leaflet-popup-pane').children().length,
+ 'The popup div should be empty');
+
+ map.destroy();
+ });
+
+ /**
+ * data: two located records
+ * asserts that all the records are shown on the map
+ */
+ QUnit.test('assert that all the records are shown on the map', async function (assert) {
+ assert.expect(3);
+
+ const map = await createView({
+ View: MapView,
+ model: 'project.task',
+ data: this.data,
+ arch: ' ',
+ mockRPC: function (route) {
+ switch (route) {
+ case '/web/dataset/search_read':
+ return Promise.resolve(this.data['project.task'].twoRecords);
+ case '/web/dataset/call_kw/res.partner/search_read':
+ return Promise.resolve(this.data['res.partner'].twoRecordsAddressNoCoordinates);
+ }
+ return Promise.resolve();
+ },
+ session: {
+ map_box_token: 'token'
+ },
+ });
+ const mapX = map.$('.leaflet-map-pane')[0]._leaflet_pos.x;
+ const mapY = map.$('.leaflet-map-pane')[0]._leaflet_pos.y;
+ assert.ok(mapX - map.$('div.leaflet-marker-icon').eq(0)[0]._leaflet_pos.x < 0,
+ 'If the marker is currently shown on the map, the subtraction of latitude should be under 0');
+ assert.ok(mapY - map.$('div.leaflet-marker-icon').eq(0)[0]._leaflet_pos.y < 0);
+ assert.strictEqual(map.$('div.leaflet-marker-icon .o_map_marker_badge').text(), '2',
+ 'There should be a marker for two records');
+
+ map.destroy();
+ });
+
+ /**
+ * data: two located records
+ * asserts that the right fields are shown in the popup
+ */
+ QUnit.test('Content of the marker popup with one field', async function (assert) {
+ assert.expect(7);
+
+ const map = await createView({
+ View: MapView,
+ model: 'project.task',
+ data: this.data,
+ arch:
+ `
+
+ `,
+ viewOptions: {
+ actionViews: [{ type: 'form' }]
+ },
+ mockRPC: function (route, args) {
+ switch (route) {
+ case '/web/dataset/search_read':
+ assert.ok(args.fields.includes('display_name'));
+ return Promise.resolve(this.data['project.task'].oneRecord);
+ case '/web/dataset/call_kw/res.partner/search_read':
+ return Promise.resolve(this.data['res.partner'].twoRecordsAddressCoordinates);
+ }
+ return Promise.resolve();
+ },
+ session: {
+ map_box_token: 'token'
+ },
+ });
+ assert.strictEqual(map.renderer.props.fieldNamesMarkerPopup[0].fieldName, "display_name");
+
+ await testUtils.dom.click(map.$('div.leaflet-marker-icon').eq(0)[0]);
+
+ assert.strictEqual(map.renderer.props.fieldNamesMarkerPopup.length, 1,
+ 'fieldsMarkerPopup should contain one field');
+ assert.strictEqual(map.$('tbody').children().children().length, 3,
+ 'The popup should have one field');
+ assert.strictEqual(map.$('tbody').children().children().eq(0).prop("innerText"), 'Name',
+ 'The first element of the table should \'Name\'');
+ assert.strictEqual(map.$('tbody').children().children().eq(2).prop("innerText"), 'Foo',
+ 'The second element of the table should \'Foo\'');
+ assert.strictEqual(map.$('div.center').children().length, 3,
+ 'The popup should contain 2 buttons and one divider');
+
+ map.destroy();
+ });
+
+ /**
+ * data: two located records
+ * asserts that no field is shown in popup
+ */
+ QUnit.test('Content of the marker with no field', async function (assert) {
+ assert.expect(2);
+
+ const map = await createView({
+ View: MapView,
+ model: 'project.task',
+ data: this.data,
+ arch: ' ',
+ viewOptions: {
+ actionViews: [{ type: 'form' }]
+ },
+ mockRPC: function (route) {
+ switch (route) {
+ case '/web/dataset/search_read':
+ return Promise.resolve(this.data['project.task'].twoRecords);
+ case '/web/dataset/call_kw/res.partner/search_read':
+ return Promise.resolve(this.data['res.partner'].twoRecordsAddressNoCoordinates);
+ }
+ return Promise.resolve();
+ },
+ session: {
+ map_box_token: 'token'
+ },
+ });
+ await testUtils.dom.click(map.$('div.leaflet-marker-icon').eq(0)[0]);
+
+ assert.strictEqual(map.$('tbody').children().length, 0,
+ 'The popup should have only the button');
+ assert.strictEqual(map.$('div.center').children().length, 3,
+ 'The popup should contain 2 buttons and one divider');
+
+ map.destroy();
+ });
+
+ QUnit.test('Attribute: hide_name', async function (assert) {
+ assert.expect(2);
+
+ const map = await createView({
+ View: MapView,
+ model: 'project.task',
+ data: this.data,
+ arch: ' ',
+ mockRPC: route => {
+ switch (route) {
+ case '/web/dataset/search_read':
+ return Promise.resolve(this.data['project.task'].twoRecords);
+ case '/web/dataset/call_kw/res.partner/search_read':
+ return Promise.resolve(this.data['res.partner'].twoRecordsAddressCoordinates);
+ }
+ return Promise.resolve();
+ },
+ session: {
+ map_box_token: 'token'
+ },
+ });
+
+ await testUtils.dom.click(map.$('div.leaflet-marker-icon').eq(0)[0]);
+
+ assert.containsOnce(map, 'tbody > tr',
+ 'The popup should have one field');
+ assert.strictEqual(map.$('tbody tr .contentName').text().trim(), 'Address',
+ 'The popup should have address field');
+
+ map.destroy();
+ });
+
+ QUnit.test('Render partner address field in popup', async function (assert) {
+ assert.expect(3);
+
+ const map = await createView({
+ View: MapView,
+ model: 'project.task',
+ data: this.data,
+ arch: ' ',
+ mockRPC: route => {
+ switch (route) {
+ case '/web/dataset/search_read':
+ return Promise.resolve(this.data['project.task'].oneRecord);
+ case '/web/dataset/call_kw/res.partner/search_read':
+ return Promise.resolve(this.data['res.partner'].oneLocatedRecord);
+ }
+ return Promise.resolve();
+ },
+ session: {
+ map_box_token: 'token'
+ },
+ });
+
+ await testUtils.dom.click(map.$('div.leaflet-marker-icon').eq(0)[0]);
+
+ assert.containsOnce(map, 'tbody tr',
+ 'The popup should have one field');
+ assert.strictEqual(map.$('tbody tr .contentName').text().trim(), 'Address',
+ 'The popup should have address field');
+ assert.strictEqual(map.$('tbody tr .contentString').text().trim(), 'Chaussée de Namur 40, 1367, Ramillies',
+ 'The popup should have correct address');
+
+ map.destroy();
+ });
+
+ QUnit.test('Hide partner address field in popup', async function (assert) {
+ assert.expect(3);
+
+ const map = await createView({
+ View: MapView,
+ model: 'project.task',
+ data: this.data,
+ arch: ' ',
+ mockRPC: route => {
+ switch (route) {
+ case '/web/dataset/search_read':
+ return Promise.resolve(this.data['project.task'].oneRecord);
+ case '/web/dataset/call_kw/res.partner/search_read':
+ return Promise.resolve(this.data['res.partner'].oneLocatedRecord);
+ }
+ return Promise.resolve();
+ },
+ session: {
+ map_box_token: 'token'
+ },
+ });
+
+ await testUtils.dom.click(map.$('div.leaflet-marker-icon').eq(0)[0]);
+
+ assert.containsOnce(map, 'tbody tr',
+ 'The popup should have one field');
+ assert.strictEqual(map.$('tbody tr .contentName').text().trim(), 'Name',
+ 'The popup should have name field');
+ assert.strictEqual(map.$('tbody tr .contentString').text().trim(), 'Foo',
+ 'The popup should have correct address');
+
+ map.destroy();
+ });
+
+ QUnit.test('Handle records of same co-ordinates in marker', async function (assert) {
+ assert.expect(4);
+
+ const map = await createView({
+ View: MapView,
+ model: 'project.task',
+ data: this.data,
+ arch: ' ',
+ mockRPC: route => {
+ switch (route) {
+ case '/web/dataset/search_read':
+ return Promise.resolve(this.data['project.task'].twoRecords);
+ case '/web/dataset/call_kw/res.partner/search_read':
+ return Promise.resolve(this.data['res.partner'].twoRecordsAddressCoordinates);
+ }
+ return Promise.resolve();
+ },
+ session: {
+ map_box_token: 'token'
+ },
+ });
+
+ assert.containsOnce(map, 'div.leaflet-marker-icon',
+ "There should be a one marker");
+ assert.strictEqual(map.$('div.leaflet-marker-icon .o_map_marker_badge').text(), '2',
+ "There should be a marker for two records");
+
+ await testUtils.dom.click(map.$('div.leaflet-marker-icon'));
+
+ assert.containsOnce(map, 'tbody tr',
+ "The popup should have one field");
+ assert.strictEqual(map.$('tbody tr .contentName').text().trim(), 'Address',
+ "The popup should have address field");
+
+ map.destroy();
+ });
+
+ QUnit.test('Pager', async function (assert) {
+ assert.expect(4);
+
+ const map = await createView({
+ View: MapView,
+ model: 'project.task',
+ data: this.data,
+ arch: ' ',
+ mockRPC: route => {
+ switch (route) {
+ case '/web/dataset/search_read':
+ return Promise.resolve({
+ length: 101,
+ records: _.range(1, 101).map(i => { return { id: i, name: 'project', partner_id: [i] }; })
+ });
+ case '/web/dataset/call_kw/res.partner/search_read':
+ return Promise.resolve(_.range(1, 101).map(i => {
+ return { id: i, name: 'Foo', 'partner_latitude': 10.0, 'partner_longitude': 10.5 };
+ }));
+ }
+ return Promise.resolve();
+ },
+ session: {
+ map_box_token: 'token'
+ },
+ });
+ assert.containsOnce(map, '.o_pager');
+ assert.strictEqual(cpHelpers.getPagerValue(map), "1-80",
+ "current pager value should be 1-20");
+ assert.strictEqual(cpHelpers.getPagerSize(map), "101",
+ "current pager limit should be 21");
+
+ await cpHelpers.pagerNext(map);
+
+ assert.strictEqual(cpHelpers.getPagerValue(map), "81-101",
+ "pager value should be 21-40");
+
+ map.destroy();
+ });
+
+ QUnit.test('New domain', async function (assert) {
+ assert.expect(18);
+
+ this.data['project.task'].records = [
+ { id: 1, name: "FooProject", sequence: 1, partner_id: 1 },
+ { id: 2, name: 'BarProject', sequence: 2, partner_id: 2 },
+ ];
+ const map = await createView({
+ View: MapView,
+ model: 'project.task',
+ data: this.data,
+ arch: ' ',
+ mockRPC: function (route) {
+ switch (route) {
+ case '/web/dataset/search_read':
+ return this._super.apply(this, arguments);
+ case '/web/dataset/call_kw/res.partner/search_read':
+ return Promise.resolve(this.data['res.partner'].twoRecordsAddressNoCoordinates);
+ }
+ return Promise.resolve();
+ },
+ session: {
+ map_box_token: 'token'
+ },
+ });
+ assert.strictEqual(map.model.data.records.length, 2,
+ 'There should be 2 records');
+ assert.containsOnce(map.$('.leaflet-overlay-pane'), 'path',
+ 'There should be one route displayed');
+ assert.strictEqual(map.$('div.leaflet-marker-icon .o_map_marker_badge').text(), '2',
+ 'There should be a marker for two records');
+
+ await map.update({ domain: [['name', '=', 'FooProject']] });
+
+ const renderer = map.renderer.componentRef.comp;
+ assert.strictEqual(map.model.data.records.length, 1,
+ 'There should be 1 record');
+ assert.strictEqual(renderer.polylines.length, 0,
+ 'There should be no road computed');
+ assert.containsNone(map.$('.leaflet-overlay-pane'), 'path',
+ 'There should be no route on the map');
+ assert.strictEqual(renderer.markers.length, 1,
+ 'There should be 1 marker generated');
+ assert.containsOnce(map, 'div.leaflet-marker-icon',
+ 'There should be 1 marker on the map');
+
+ await map.update({ domain: [['name', '=', 'Foofezfezf']] });
+
+ assert.strictEqual(map.model.data.records.length, 0,
+ 'There should be no record');
+ assert.strictEqual(renderer.polylines.length, 0,
+ 'There should be no road computed');
+ assert.containsNone(map.$('.leaflet-overlay-pane'), 'path',
+ 'There should be no route on the map');
+ assert.strictEqual(renderer.markers.length, 0,
+ 'There should be no marker generated');
+ assert.containsNone(map, 'div.leaflet-marker-icon',
+ 'There should be 0 marker on the map');
+
+ await map.update({ domain: [['name', 'like', 'Project']] });
+
+ assert.strictEqual(map.model.data.records.length, 2,
+ 'There should be 2 record');
+ assert.strictEqual(renderer.polylines.length, 1,
+ 'There should be one road computed');
+ assert.containsOnce(map.$('.leaflet-overlay-pane'), 'path',
+ 'There should be 1 route on the map');
+ assert.strictEqual(renderer.markers.length, 1,
+ 'There should be 1 marker generated');
+ assert.strictEqual(map.$('div.leaflet-marker-icon .o_map_marker_badge').text(), '2',
+ 'There should be a marker for two records');
+
+ map.destroy();
+ });
+
+ QUnit.test('Toggle grouped pin lists', async function (assert) {
+ assert.expect(13);
+
+ const records = this.data['project.task'].threeRecords;
+ const partners = this.data['res.partner'].twoRecordsAddressCoordinates;
+ for (const record of records.records) {
+ // add name on partner_id to have name_get like value
+ record.partner_id.push(partners.find(x => x.id === record.partner_id[0]).name);
+ }
+
+ const map = await createView({
+ View: MapView,
+ model: 'project.task',
+ data: this.data,
+ arch: ' ',
+ async mockRPC(route) {
+ switch (route) {
+ case '/web/dataset/search_read':
+ return records;
+ case '/web/dataset/call_kw/res.partner/search_read':
+ return partners;
+ }
+ },
+ session: {
+ map_box_token: 'token'
+ },
+ groupBy: ['partner_id'],
+ });
+
+ assert.containsN(map, '.o_pin_list_group_header', 2, 'Should have 2 groups');
+ assert.strictEqual(map.$('.o_pin_list_group_header').text(), 'BarFoo');
+ assert.containsN(map, '.o_pin_list_details', 2);
+ assert.containsN(map, '.o_pin_list_details li', 3);
+ assert.strictEqual(map.$('.o_pin_list_details').text(), 'FooProjectFooBarProjectBarProject');
+
+ await testUtils.dom.click(map.$('.o_pin_list_group_header:eq(1)'));
+
+ assert.containsN(map, '.o_pin_list_group_header', 2, 'Should still have 2 groups');
+ assert.containsOnce(map, '.o_pin_list_details');
+ assert.containsN(map, '.o_pin_list_details li', 2);
+ assert.strictEqual(map.$('.o_pin_list_details').text(), 'FooProjectFooBarProject');
+
+ await testUtils.dom.click(map.$('.o_pin_list_group_header:eq(0)'));
+
+ assert.containsNone(map, '.o_pin_list_details');
+
+ await testUtils.dom.click(map.$('.o_pin_list_group_header:eq(1)'));
+
+ assert.containsOnce(map, '.o_pin_list_details');
+ assert.containsOnce(map, '.o_pin_list_details li');
+ assert.strictEqual(map.$('.o_pin_list_details').text(), 'BarProject');
+
+ map.destroy();
+ });
+
+ QUnit.test('Change groupBy', async function (assert) {
+ assert.expect(13);
+
+ const records = this.data['project.task'].threeRecords;
+ const partners = this.data['res.partner'].twoRecordsAddressCoordinates;
+ for (const record of records.records) {
+ // add name on partner_id to have name_get like value
+ record.partner_id.push(partners.find(x => x.id === record.partner_id[0]).name);
+ }
+
+ const map = await createView({
+ View: MapView,
+ model: 'project.task',
+ data: this.data,
+ arch: ' ',
+ archs: {
+ 'project.task,false,search': `
+
+
+
+
+ `,
+ },
+ session: {
+ map_box_token: 'token'
+ },
+ async mockRPC(route) {
+ switch (route) {
+ case '/web/dataset/search_read':
+ return records;
+ case '/web/dataset/call_kw/res.partner/search_read':
+ return partners;
+ }
+ },
+ });
+
+ assert.containsNone(map, '.o_pin_list_group_header', 'Should not have any groups');
+
+ await cpHelpers.toggleGroupByMenu(map);
+ await cpHelpers.toggleMenuItem(map, 'Partner');
+
+ assert.containsN(map, '.o_pin_list_group_header', 2, 'Should have 2 groups');
+ assert.strictEqual(map.$('.o_pin_list_group_header').text(), 'BarFoo');
+ // Groups should be loaded too
+ assert.containsN(map, '.o_pin_list_details li', 3);
+ assert.strictEqual(map.$('.o_pin_list_details').text(), 'FooProjectFooBarProjectBarProject');
+
+ await cpHelpers.toggleMenuItem(map, 'Name');
+
+ assert.strictEqual(map.$('.o_pin_list_group_header').text(), 'BarFoo', 'Should not have changed');
+ assert.strictEqual(map.$('.o_pin_list_details').text(), 'FooProjectFooBarProjectBarProject');
+
+ await cpHelpers.toggleMenuItem(map, 'Partner');
+
+ assert.containsN(map, '.o_pin_list_group_header', 3, 'Should have 3 groups');
+ assert.strictEqual(map.$('.o_pin_list_group_header').text(), 'FooProjectBarProjectFooBarProject');
+ assert.strictEqual(map.$('.o_pin_list_details').text(), 'FooProjectBarProjectFooBarProject');
+ assert.containsOnce(map, '.o_pin_list_details:eq(0) li');
+ assert.containsOnce(map, '.o_pin_list_details:eq(1) li');
+ assert.containsOnce(map, '.o_pin_list_details:eq(2) li');
+
+ map.destroy();
+ });
+
+ //--------------------------------------------------------------------------
+ // Controller testing
+ //--------------------------------------------------------------------------
+
+ QUnit.test('Click on open button switches to form view', async function (assert) {
+ assert.expect(7);
+
+ const map = await createView({
+ View: MapView,
+ model: 'project.task',
+ data: this.data,
+ arch: ' ',
+ viewOptions: {
+ actionViews: [{ type: 'form' }]
+ },
+ mockRPC: function (route) {
+ switch (route) {
+ case '/web/dataset/search_read':
+ return Promise.resolve(this.data['project.task'].oneRecord);
+ case '/web/dataset/call_kw/res.partner/search_read':
+ return Promise.resolve(this.data['res.partner'].oneLocatedRecord);
+ }
+ return Promise.resolve();
+ },
+ session: {
+ map_box_token: 'token'
+ },
+ });
+ testUtils.mock.intercept(map, 'switch_view', function (event) {
+ assert.strictEqual(event.name, 'switch_view',
+ 'The custom event should be \'switch_view\'');
+ assert.strictEqual(event.data.view_type, 'form',
+ 'The view switched to should be form');
+ assert.strictEqual(event.data.res_id, 1,
+ 'The record\'s id should be 1');
+ assert.strictEqual(event.data.mode, 'readonly',
+ 'The mode should be readonly');
+ assert.strictEqual(event.data.model, 'project.task',
+ 'The form view should be on the \'res.partner\' model');
+ });
+ testUtils.mock.intercept(map, 'open_clicked', function (event) {
+ assert.deepEqual(event.data.ids, [1], 'The record\'s id should be 1');
+
+ }, true);
+
+ await testUtils.dom.click(map.$('div.leaflet-marker-icon').eq(0));
+ await testUtils.dom.click(map.$('div.center').children().eq(0));
+
+ assert.containsOnce(map.$('div.leaflet-popup-pane'), 'button.btn.btn-primary.o_open',
+ 'The button should be present in the dom');
+
+ map.destroy();
+ });
+
+ QUnit.test('Test the lack of open button', async function (assert) {
+ assert.expect(1);
+
+ const map = await createView({
+ View: MapView,
+ model: 'project.task',
+ data: this.data,
+ arch: ' ',
+ mockRPC: function (route) {
+ switch (route) {
+ case '/web/dataset/search_read':
+ return Promise.resolve(this.data['project.task'].oneRecord);
+ case '/web/dataset/call_kw/res.partner/search_read':
+ return Promise.resolve(this.data['res.partner'].oneLocatedRecord);
+ }
+ return Promise.resolve();
+ },
+ session: {
+ map_box_token: 'token'
+ },
+ });
+
+ await testUtils.dom.click(map.$('div.leaflet-marker-icon').eq(0));
+
+ assert.containsNone(map.$('div.leaflet-popup-pane'), 'button.btn.btn-primary.open',
+ 'The button should not be present in the dom');
+
+ map.destroy();
+ });
+
+ QUnit.test('attribute panel_title on the arch should display in the pin list', async function (assert) {
+ assert.expect(1);
+
+ const map = await createView({
+ View: MapView,
+ model: 'project.task',
+ data: this.data,
+ arch: ' ',
+ mockRPC: function (route) {
+ switch (route) {
+ case '/web/dataset/search_read':
+ return Promise.resolve(this.data['project.task'].oneRecord);
+ case '/web/dataset/call_kw/res.partner/search_read':
+ return Promise.resolve(this.data['res.partner'].oneLocatedRecord);
+ }
+ return Promise.resolve();
+ },
+ session: {
+ },
+ });
+ assert.strictEqual(map.$('.o_pin_list_container .o_pin_list_header span').text(),
+ 'AAAAAAAAAAAAAAAAA');
+
+ map.destroy();
+ });
+
+ QUnit.test('Test using a field other than partner_id for the map view', async function (assert) {
+ assert.expect(1);
+
+ const map = await createView({
+ View: MapView,
+ model: 'project.task',
+ data: this.data,
+ arch: ' ',
+ mockRPC: function (route) {
+ switch (route) {
+ case '/web/dataset/search_read':
+ return Promise.resolve(this.data['project.task'].anotherPartnerId);
+ case '/web/dataset/call_kw/res.partner/search_read':
+ return Promise.resolve(this.data['res.partner'].oneLocatedRecord);
+ }
+ return Promise.resolve();
+ },
+ session: {
+ map_box_token: 'token'
+ },
+ });
+
+ await testUtils.dom.click(map.$('div.leaflet-marker-icon').eq(0));
+
+ assert.containsNone(map.$('div.leaflet-popup-pane'), 'button.btn.btn-primary.open',
+ 'The button should not be present in the dom');
+
+ map.destroy();
+ });
+});
+
+});
diff --git a/odex30_base/odex30_web_map/validation.py b/odex30_base/odex30_web_map/validation.py
new file mode 100644
index 0000000..ccbe32d
--- /dev/null
+++ b/odex30_base/odex30_web_map/validation.py
@@ -0,0 +1,30 @@
+# -*- coding: utf-8 -*-
+
+
+import logging
+import os
+
+from lxml import etree
+
+from odoo.loglevels import ustr
+from odoo.tools import misc, view_validation
+
+_logger = logging.getLogger(__name__)
+
+_map_view_validator = None
+
+
+@view_validation.validate('map')
+def schema_map_view(arch, **kwargs):
+ global _map_view_validator
+
+ if _map_view_validator is None:
+ with misc.file_open(os.path.join('odex30_web_map', 'views', 'odex30_web_map.rng')) as f:
+ _map_view_validator = etree.RelaxNG(etree.parse(f))
+
+ if _map_view_validator.validate(arch):
+ return True
+
+ for error in _map_view_validator.error_log:
+ _logger.error(ustr(error))
+ return False
diff --git a/odex30_base/odex30_web_map/views/assets.xml b/odex30_base/odex30_web_map/views/assets.xml
new file mode 100644
index 0000000..36d4a98
--- /dev/null
+++ b/odex30_base/odex30_web_map/views/assets.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/odex30_base/odex30_web_map/views/odex25_web_map.rng b/odex30_base/odex30_web_map/views/odex25_web_map.rng
new file mode 100644
index 0000000..13f8cd5
--- /dev/null
+++ b/odex30_base/odex30_web_map/views/odex25_web_map.rng
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/odex30_base/odex30_web_map/views/res_config_settings.xml b/odex30_base/odex30_web_map/views/res_config_settings.xml
new file mode 100644
index 0000000..bead626
--- /dev/null
+++ b/odex30_base/odex30_web_map/views/res_config_settings.xml
@@ -0,0 +1,31 @@
+
+
+
+ res.config.settings.view.form.inherit.map
+ res.config.settings
+
+
+
+
+
+
+
Map Routes
+
+
+ Set a MapBox account to activate routes and style
+
+
+
+
+
+
+
+
+
+
+
diff --git a/odex30_base/odex30_web_map/views/res_partner_views.xml b/odex30_base/odex30_web_map/views/res_partner_views.xml
new file mode 100644
index 0000000..dd50b4c
--- /dev/null
+++ b/odex30_base/odex30_web_map/views/res_partner_views.xml
@@ -0,0 +1,14 @@
+
+
+
+ res.partner.form.inherit.map
+ res.partner
+
+
+
+
+
+
+
+
+
diff --git a/odex30_base/os_whatsapp_integration/__init__.py b/odex30_base/os_whatsapp_integration/__init__.py
new file mode 100644
index 0000000..9b42961
--- /dev/null
+++ b/odex30_base/os_whatsapp_integration/__init__.py
@@ -0,0 +1,2 @@
+from . import models
+from . import wizard
diff --git a/odex30_base/os_whatsapp_integration/__manifest__.py b/odex30_base/os_whatsapp_integration/__manifest__.py
new file mode 100644
index 0000000..4141570
--- /dev/null
+++ b/odex30_base/os_whatsapp_integration/__manifest__.py
@@ -0,0 +1,32 @@
+{
+ 'name': 'Odoo Whatsapp Integration',
+ 'version': '18.0.1.0',
+ 'summary': 'Odoo Whatsapp Integration',
+ 'author': 'Odosquare',
+ 'company': 'Odosquare',
+ 'maintainer': 'Odosquare',
+ 'sequence': 4,
+ 'images': ['static/description/Banner.png'],
+ 'license': 'LGPL-3',
+ 'description': """Odoo Whatsapp Integration""",
+ 'category': 'Connector',
+ 'depends': [
+ 'base', 'contacts', 'sale', 'crm', 'stock', 'sale_management', 'account', 'purchase'
+ ],
+ 'data': [
+ 'security/ir.model.access.csv',
+ 'data/whatsapp_template.xml',
+ 'views/sale_wa.xml',
+ 'views/crm_wa.xml',
+ 'views/purchase_wa.xml',
+ 'views/stock_wa.xml',
+ 'views/invoice_wa.xml',
+ 'views/contact_wa.xml',
+ 'wizard/wizard.xml',
+ ],
+ 'demo': [],
+ 'qweb': [],
+ 'installable': True,
+ 'application': False,
+ 'auto_install': False,
+}
diff --git a/odex30_base/os_whatsapp_integration/data/whatsapp_template.xml b/odex30_base/os_whatsapp_integration/data/whatsapp_template.xml
new file mode 100644
index 0000000..85e7033
--- /dev/null
+++ b/odex30_base/os_whatsapp_integration/data/whatsapp_template.xml
@@ -0,0 +1,109 @@
+
+
+
+
+ Sales: Confirm Order
+ Sales Confirm
+
+
+ Hello *${object.partner_id.name or ''}*,
+ Your order ${object.name} amount *${format_amount(object.amount_total, object.currency_id)}* is Confirmed.
+
+ Kindly refer below link for order receipt.
+
+ ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Purchase: Confirm Order
+ Purchase Order
+
+
+
+ Dear ${object.partner_id.name}
+ % if object.partner_id.parent_id:
+ (${object.partner_id.parent_id.name})
+ % endif
+
+ Here is in attachment a purchase order ${object.name}
+ % if object.partner_ref:
+ with reference: ${object.partner_ref}
+ % endif
+ amounting in ${format_amount(object.amount_total, object.currency_id)}
+ from ${object.company_id.name}.
+
+ If you have any questions, please do not hesitate to contact us.
+
+ Best regards,
+
+ ]]>
+
+
+
+
+
+ Invoice: Send by WhatsApp
+
+ Purchase Order
+
+
+ Dear
+ % if object.partner_id.parent_id:
+ ${object.partner_id.name} (${object.partner_id.parent_id.name}),
+ % else:
+ ${object.partner_id.name},
+ % endif
+
+ Here is your
+ % if object.name:
+ invoice ${object.name}
+ % else:
+ invoice
+ %endif
+ % if object.invoice_origin:
+ (with reference: ${object.invoice_origin})
+ % endif
+ amounting in ${format_amount(object.amount_total, object.currency_id)}
+ from ${object.company_id.name}.
+ % if object.payment_state == 'paid':
+ This invoice is already paid.
+ % else:
+ Please remit payment at your earliest convenience.
+ % if object.payment_reference:
+
+ Please use the following communication for your payment: ${object.payment_reference} .
+ % endif
+ % endif
+
+ Do not hesitate to contact us if you have any questions.
+ % if object.invoice_user_id.signature:
+
+ ${object.invoice_user_id.signature | safe}
+ % endif
+
+ ]]>
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/odex30_base/os_whatsapp_integration/models/__init__.py b/odex30_base/os_whatsapp_integration/models/__init__.py
new file mode 100644
index 0000000..1332c92
--- /dev/null
+++ b/odex30_base/os_whatsapp_integration/models/__init__.py
@@ -0,0 +1,6 @@
+from . import contacts_wa
+from . import crm_wa
+from . import invoice_wa
+from . import purchase_wa
+from . import sale_wa
+from . import stock_wa
diff --git a/odex30_base/os_whatsapp_integration/models/contacts_wa.py b/odex30_base/os_whatsapp_integration/models/contacts_wa.py
new file mode 100644
index 0000000..390dfae
--- /dev/null
+++ b/odex30_base/os_whatsapp_integration/models/contacts_wa.py
@@ -0,0 +1,15 @@
+from odoo import _, models
+
+
+class ResPartner(models.Model):
+ _inherit = 'res.partner'
+
+ def contacts_whatsapp(self):
+ return {'type': 'ir.actions.act_window',
+ 'name': _('Whatsapp Message'),
+ 'res_model': 'whatsapp.message.wizard',
+ 'target': 'new',
+ 'view_mode': 'form',
+ 'view_type': 'form',
+ 'context': {'default_user_id': self.id},
+ }
diff --git a/odex30_base/os_whatsapp_integration/models/crm_wa.py b/odex30_base/os_whatsapp_integration/models/crm_wa.py
new file mode 100644
index 0000000..baedffd
--- /dev/null
+++ b/odex30_base/os_whatsapp_integration/models/crm_wa.py
@@ -0,0 +1,15 @@
+from odoo import _, models
+
+
+class WhatsappCrm(models.Model):
+ _inherit = 'crm.lead'
+
+ def crm_whatsapp(self):
+ return {'type': 'ir.actions.act_window',
+ 'name': _('Whatsapp Message'),
+ 'res_model': 'whatsapp.message.wizard',
+ 'target': 'new',
+ 'view_mode': 'form',
+ 'view_type': 'form',
+ 'context': {'default_user_id': self.partner_id.id},
+ }
diff --git a/odex30_base/os_whatsapp_integration/models/invoice_wa.py b/odex30_base/os_whatsapp_integration/models/invoice_wa.py
new file mode 100644
index 0000000..54c362a
--- /dev/null
+++ b/odex30_base/os_whatsapp_integration/models/invoice_wa.py
@@ -0,0 +1,15 @@
+from odoo import _, models
+
+
+class WhatsappInvoice(models.Model):
+ _inherit = 'account.move'
+
+ def invoice_whatsapp(self):
+ return {'type': 'ir.actions.act_window',
+ 'name': _('Whatsapp Message'),
+ 'res_model': 'whatsapp.message.wizard',
+ 'target': 'new',
+ 'view_mode': 'form',
+ 'view_type': 'form',
+ 'context': {'default_template_id': self.env.ref('os_whatsapp_integration.invoice_whatsapp_template').id},
+ }
diff --git a/odex30_base/os_whatsapp_integration/models/purchase_wa.py b/odex30_base/os_whatsapp_integration/models/purchase_wa.py
new file mode 100644
index 0000000..3252a66
--- /dev/null
+++ b/odex30_base/os_whatsapp_integration/models/purchase_wa.py
@@ -0,0 +1,15 @@
+from odoo import _, models
+
+
+class WhatsappPurchase(models.Model):
+ _inherit = 'purchase.order'
+
+ def purchase_whatsapp(self):
+ return {'type': 'ir.actions.act_window',
+ 'name': _('Whatsapp Message'),
+ 'res_model': 'whatsapp.message.wizard',
+ 'target': 'new',
+ 'view_mode': 'form',
+ 'view_type': 'form',
+ 'context': {'default_template_id': self.env.ref('os_whatsapp_integration.purchase_whatsapp_template').id},
+ }
diff --git a/odex30_base/os_whatsapp_integration/models/sale_wa.py b/odex30_base/os_whatsapp_integration/models/sale_wa.py
new file mode 100644
index 0000000..f3ee857
--- /dev/null
+++ b/odex30_base/os_whatsapp_integration/models/sale_wa.py
@@ -0,0 +1,15 @@
+from odoo import _, models
+
+
+class WhatsappSale(models.Model):
+ _inherit = 'sale.order'
+
+ def sale_whatsapp(self):
+ return {'type': 'ir.actions.act_window',
+ 'name': _('Whatsapp Message'),
+ 'res_model': 'whatsapp.message.wizard',
+ 'target': 'new',
+ 'view_mode': 'form',
+ 'view_type': 'form',
+ 'context': {'default_template_id': self.env.ref('os_whatsapp_integration.sales_whatsapp_template').id},
+ }
diff --git a/odex30_base/os_whatsapp_integration/models/stock_wa.py b/odex30_base/os_whatsapp_integration/models/stock_wa.py
new file mode 100644
index 0000000..8a8c586
--- /dev/null
+++ b/odex30_base/os_whatsapp_integration/models/stock_wa.py
@@ -0,0 +1,15 @@
+from odoo import _, models
+
+
+class WhatsappPurchase(models.Model):
+ _inherit = 'stock.picking'
+
+ def stock_whatsapp(self):
+ return {'type': 'ir.actions.act_window',
+ 'name': _('Whatsapp Message'),
+ 'res_model': 'whatsapp.message.wizard',
+ 'target': 'new',
+ 'view_mode': 'form',
+ 'view_type': 'form',
+ 'context': {'default_user_id': self.partner_id.id},
+ }
diff --git a/odex30_base/os_whatsapp_integration/security/ir.model.access.csv b/odex30_base/os_whatsapp_integration/security/ir.model.access.csv
new file mode 100644
index 0000000..ace71c3
--- /dev/null
+++ b/odex30_base/os_whatsapp_integration/security/ir.model.access.csv
@@ -0,0 +1,2 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+access_group_user,Access User,model_whatsapp_message_wizard,base.group_user,1,1,1,1
\ No newline at end of file
diff --git a/odex30_base/os_whatsapp_integration/static/description/Banner.png b/odex30_base/os_whatsapp_integration/static/description/Banner.png
new file mode 100644
index 0000000..576d326
Binary files /dev/null and b/odex30_base/os_whatsapp_integration/static/description/Banner.png differ
diff --git a/odex30_base/os_whatsapp_integration/static/description/feature/account.png b/odex30_base/os_whatsapp_integration/static/description/feature/account.png
new file mode 100644
index 0000000..e3a38a7
Binary files /dev/null and b/odex30_base/os_whatsapp_integration/static/description/feature/account.png differ
diff --git a/odex30_base/os_whatsapp_integration/static/description/feature/contacts.png b/odex30_base/os_whatsapp_integration/static/description/feature/contacts.png
new file mode 100644
index 0000000..4d179a9
Binary files /dev/null and b/odex30_base/os_whatsapp_integration/static/description/feature/contacts.png differ
diff --git a/odex30_base/os_whatsapp_integration/static/description/feature/crm.png b/odex30_base/os_whatsapp_integration/static/description/feature/crm.png
new file mode 100644
index 0000000..65ebc4f
Binary files /dev/null and b/odex30_base/os_whatsapp_integration/static/description/feature/crm.png differ
diff --git a/odex30_base/os_whatsapp_integration/static/description/feature/purchase.png b/odex30_base/os_whatsapp_integration/static/description/feature/purchase.png
new file mode 100644
index 0000000..02b7321
Binary files /dev/null and b/odex30_base/os_whatsapp_integration/static/description/feature/purchase.png differ
diff --git a/odex30_base/os_whatsapp_integration/static/description/feature/sale.png b/odex30_base/os_whatsapp_integration/static/description/feature/sale.png
new file mode 100644
index 0000000..343c9f7
Binary files /dev/null and b/odex30_base/os_whatsapp_integration/static/description/feature/sale.png differ
diff --git a/odex30_base/os_whatsapp_integration/static/description/feature/stock.png b/odex30_base/os_whatsapp_integration/static/description/feature/stock.png
new file mode 100644
index 0000000..692e762
Binary files /dev/null and b/odex30_base/os_whatsapp_integration/static/description/feature/stock.png differ
diff --git a/odex30_base/os_whatsapp_integration/static/description/icon.png b/odex30_base/os_whatsapp_integration/static/description/icon.png
new file mode 100644
index 0000000..bf312cd
Binary files /dev/null and b/odex30_base/os_whatsapp_integration/static/description/icon.png differ
diff --git a/odex30_base/os_whatsapp_integration/static/description/index.html b/odex30_base/os_whatsapp_integration/static/description/index.html
new file mode 100644
index 0000000..6388933
--- /dev/null
+++ b/odex30_base/os_whatsapp_integration/static/description/index.html
@@ -0,0 +1,172 @@
+
+
+
Odoo WhatsApp Integration
+
+
+
+
+
Now Send Messages to the customers and partners
+ through WhatsApp. The WhatsApp feature is available in the modules Sales, CRM, Purchase, Invoice, Inventory and
+ Contacts. With this feature, the communication between the partners become more easier as the new technologies.
+
+
+
+
+
+
+
+ Available in
+
+
+
+
+
+
+
+
+
+
Using WhatsApp For Customer Communication
+ Direct chat with the contacts in the contacts module through WhatsApp
+
+
+
+
+
+
+
+
+
+
Creative Usage Of WhatsApp For Business
+ Grow your business profitably and creatively. Use WhatsApp as an extra sales channel. Easy to send the Quotation, Sale Order, etc... related files to the corresponding partners
+
+
+
+
+
+
+
+
+
+
+
+
Using WhatsApp For Marketing & Promotion
+ WhatsApp can be a very solid marketing tool. It is a good individual platform for direct communication. You can use WhatsApp to send images, audio files, short videos of your products and more.
+
+
+
+
+
+
+
+
+
+
Using WhatsApp For payment reminder
+ Whatsapp will help you bill more, faster and control and speed up your collection process.
+
+
+
+
+
+
+
+
+
+
+
+
Quick collection of accounts receivable, payment reminder
+ Your collection team will have an additional communication channel to streamline your accounts receivable process.
+
+
+
+
+
+
+
+
+
+
Using WhatsApp For Customer Support
+ Our customers would always prefer to send you a message over WhatsApp rather than calling a helpdesk number or raising a ticket.
+
+
+
+
+
+
+
+
+
+
+
Contacts
+
+
+
+
+
+
+
+
+
+
+
Invoice
+
+
+
+
+
+
+
+
+
+
Purchase
+
+
+
+
+
+
+
+
+
+
Inventory
+
+
+
+
+
+
+
+
+
CRM
+
+
+
+
+
+
+
+
+
+
+
+
+
If you have any queries or doubt just contact us:
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/odex30_base/os_whatsapp_integration/static/description/what_index/contact1.jpg b/odex30_base/os_whatsapp_integration/static/description/what_index/contact1.jpg
new file mode 100755
index 0000000..9da2d9e
Binary files /dev/null and b/odex30_base/os_whatsapp_integration/static/description/what_index/contact1.jpg differ
diff --git a/odex30_base/os_whatsapp_integration/static/description/what_index/contact2.jpg b/odex30_base/os_whatsapp_integration/static/description/what_index/contact2.jpg
new file mode 100644
index 0000000..b37c618
Binary files /dev/null and b/odex30_base/os_whatsapp_integration/static/description/what_index/contact2.jpg differ
diff --git a/odex30_base/os_whatsapp_integration/static/description/what_index/crm1.jpg b/odex30_base/os_whatsapp_integration/static/description/what_index/crm1.jpg
new file mode 100755
index 0000000..143f890
Binary files /dev/null and b/odex30_base/os_whatsapp_integration/static/description/what_index/crm1.jpg differ
diff --git a/odex30_base/os_whatsapp_integration/static/description/what_index/invoice1.jpg b/odex30_base/os_whatsapp_integration/static/description/what_index/invoice1.jpg
new file mode 100755
index 0000000..383f1cb
Binary files /dev/null and b/odex30_base/os_whatsapp_integration/static/description/what_index/invoice1.jpg differ
diff --git a/odex30_base/os_whatsapp_integration/static/description/what_index/invoice2.jpg b/odex30_base/os_whatsapp_integration/static/description/what_index/invoice2.jpg
new file mode 100644
index 0000000..1f9f9d2
Binary files /dev/null and b/odex30_base/os_whatsapp_integration/static/description/what_index/invoice2.jpg differ
diff --git a/odex30_base/os_whatsapp_integration/static/description/what_index/purchase1.jpg b/odex30_base/os_whatsapp_integration/static/description/what_index/purchase1.jpg
new file mode 100755
index 0000000..380c9de
Binary files /dev/null and b/odex30_base/os_whatsapp_integration/static/description/what_index/purchase1.jpg differ
diff --git a/odex30_base/os_whatsapp_integration/static/description/what_index/purchase2.jpg b/odex30_base/os_whatsapp_integration/static/description/what_index/purchase2.jpg
new file mode 100644
index 0000000..e02e215
Binary files /dev/null and b/odex30_base/os_whatsapp_integration/static/description/what_index/purchase2.jpg differ
diff --git a/odex30_base/os_whatsapp_integration/static/description/what_index/sale1.jpg b/odex30_base/os_whatsapp_integration/static/description/what_index/sale1.jpg
new file mode 100755
index 0000000..f278db6
Binary files /dev/null and b/odex30_base/os_whatsapp_integration/static/description/what_index/sale1.jpg differ
diff --git a/odex30_base/os_whatsapp_integration/static/description/what_index/sale2.jpg b/odex30_base/os_whatsapp_integration/static/description/what_index/sale2.jpg
new file mode 100644
index 0000000..8158fb7
Binary files /dev/null and b/odex30_base/os_whatsapp_integration/static/description/what_index/sale2.jpg differ
diff --git a/odex30_base/os_whatsapp_integration/static/description/what_index/sale3.jpg b/odex30_base/os_whatsapp_integration/static/description/what_index/sale3.jpg
new file mode 100755
index 0000000..2e1995b
Binary files /dev/null and b/odex30_base/os_whatsapp_integration/static/description/what_index/sale3.jpg differ
diff --git a/odex30_base/os_whatsapp_integration/static/description/what_index/stock1.jpg b/odex30_base/os_whatsapp_integration/static/description/what_index/stock1.jpg
new file mode 100755
index 0000000..a0086f5
Binary files /dev/null and b/odex30_base/os_whatsapp_integration/static/description/what_index/stock1.jpg differ
diff --git a/odex30_base/os_whatsapp_integration/views/contact_wa.xml b/odex30_base/os_whatsapp_integration/views/contact_wa.xml
new file mode 100644
index 0000000..d279c07
--- /dev/null
+++ b/odex30_base/os_whatsapp_integration/views/contact_wa.xml
@@ -0,0 +1,18 @@
+
+
+
+
+ whatsapp.view.form.inherit.res
+ res.partner
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/odex30_base/os_whatsapp_integration/views/crm_wa.xml b/odex30_base/os_whatsapp_integration/views/crm_wa.xml
new file mode 100644
index 0000000..8926f41
--- /dev/null
+++ b/odex30_base/os_whatsapp_integration/views/crm_wa.xml
@@ -0,0 +1,16 @@
+
+
+
+
+ whatsapp.view.form.inherit.crm
+ crm.lead
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/odex30_base/os_whatsapp_integration/views/invoice_wa.xml b/odex30_base/os_whatsapp_integration/views/invoice_wa.xml
new file mode 100644
index 0000000..125c3db
--- /dev/null
+++ b/odex30_base/os_whatsapp_integration/views/invoice_wa.xml
@@ -0,0 +1,17 @@
+
+
+
+
+ whatsapp.view.form.inherit.account
+ account.move
+
+
+
+
+
+
+
diff --git a/odex30_base/os_whatsapp_integration/views/purchase_wa.xml b/odex30_base/os_whatsapp_integration/views/purchase_wa.xml
new file mode 100644
index 0000000..2f62241
--- /dev/null
+++ b/odex30_base/os_whatsapp_integration/views/purchase_wa.xml
@@ -0,0 +1,16 @@
+
+
+
+
+ whatsapp.view.form.inherit.purchase
+ purchase.order
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/odex30_base/os_whatsapp_integration/views/sale_wa.xml b/odex30_base/os_whatsapp_integration/views/sale_wa.xml
new file mode 100644
index 0000000..897abfd
--- /dev/null
+++ b/odex30_base/os_whatsapp_integration/views/sale_wa.xml
@@ -0,0 +1,17 @@
+
+
+
+
+ whatsapp.view.form.inherit.sale
+ sale.order
+
+
+
+
+
+
+
diff --git a/odex30_base/os_whatsapp_integration/views/stock_wa.xml b/odex30_base/os_whatsapp_integration/views/stock_wa.xml
new file mode 100644
index 0000000..bccbed3
--- /dev/null
+++ b/odex30_base/os_whatsapp_integration/views/stock_wa.xml
@@ -0,0 +1,16 @@
+
+
+
+
+ whatsapp.view.form.inherit.stock
+ stock.picking
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/odex30_base/os_whatsapp_integration/wizard/__init__.py b/odex30_base/os_whatsapp_integration/wizard/__init__.py
new file mode 100644
index 0000000..4027237
--- /dev/null
+++ b/odex30_base/os_whatsapp_integration/wizard/__init__.py
@@ -0,0 +1 @@
+from . import wizard
diff --git a/odex30_base/os_whatsapp_integration/wizard/wizard.py b/odex30_base/os_whatsapp_integration/wizard/wizard.py
new file mode 100644
index 0000000..720eb48
--- /dev/null
+++ b/odex30_base/os_whatsapp_integration/wizard/wizard.py
@@ -0,0 +1,51 @@
+from odoo import api, fields, models
+import html2text
+
+
+class WhatsappSendMessage(models.TransientModel):
+ _name = 'whatsapp.message.wizard'
+ _description = 'Whatsapp Message Wizard'
+
+ user_id = fields.Many2one('res.partner', string="Recipient")
+ mobile = fields.Char(related='user_id.mobile', required=True, readonly=False)
+ message = fields.Text(string="Message")
+ model = fields.Char('Related Document Model')
+ template_id = fields.Many2one(
+ 'mail.template', 'Use template', index=True,
+ domain="[('model', '=', model)]"
+ )
+
+ @api.onchange('template_id')
+ def _onchange_template_id(self):
+ """
+ Renders the selected template and populates the message field.
+ This is the correct method for Odoo 17/18.
+ """
+ if self.template_id:
+ res_id = self._context.get('active_id')
+ # Render the template's body_html field for the active record
+ rendered_html = self.template_id._render_field('body_html', [res_id], compute_lang=True)[res_id]
+ # Convert the rendered HTML to plain text suitable for WhatsApp
+ self.message = html2text.html2text(rendered_html)
+
+ def send_message(self):
+ """
+ Generates the WhatsApp Web URL and opens it in a new tab.
+ """
+ self.ensure_one()
+ if self.message and self.mobile:
+ # Properly encode the message for a URL, handling spaces and new lines
+ message_string = self.message.replace(' ', '%20').replace('\n', '%0A')
+
+ # Sanitize the mobile number for the URL
+ number = self.mobile.replace('+', '').replace(' ', '')
+
+ link = f"https://web.whatsapp.com/send?phone={number}&text={message_string}"
+
+ return {
+ 'type': 'ir.actions.act_url',
+ 'url': link,
+ 'target': 'new',
+ }
+ return True
+
diff --git a/odex30_base/os_whatsapp_integration/wizard/wizard.xml b/odex30_base/os_whatsapp_integration/wizard/wizard.xml
new file mode 100644
index 0000000..8d0ba3b
--- /dev/null
+++ b/odex30_base/os_whatsapp_integration/wizard/wizard.xml
@@ -0,0 +1,32 @@
+
+
+
+
+ whatsapp.message.wizard.form
+ whatsapp.message.wizard
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/odex30_base/ps_dynamic_report/__init__.py b/odex30_base/ps_dynamic_report/__init__.py
new file mode 100644
index 0000000..cde864b
--- /dev/null
+++ b/odex30_base/ps_dynamic_report/__init__.py
@@ -0,0 +1,3 @@
+# -*- coding: utf-8 -*-
+
+from . import models
diff --git a/odex30_base/ps_dynamic_report/__manifest__.py b/odex30_base/ps_dynamic_report/__manifest__.py
new file mode 100644
index 0000000..3fe62af
--- /dev/null
+++ b/odex30_base/ps_dynamic_report/__manifest__.py
@@ -0,0 +1,46 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) PySquad Informetics ( ).
+#
+# For Module Support : contact@pysquad.com
+#
+##############################################################################
+
+{
+ # Module Information
+ "name": "Dynamic Report",
+ "version": "18.0.1.0.0",
+ "category": "Odex30-base",
+ "description": "Export to pdf and xls in one click",
+ "summary": """
+ Dynamic Report
+ Export Tree View PDF
+ Export Tree View XLSx
+ Creating Fully Dynamically Pdf & XLS report.
+ """,
+
+ # Author
+ "author": "Pysquad Informatics LLP",
+ "website": "https://www.pysquad.com",
+ "license": "LGPL-3",
+
+ # Dependencies
+ "depends": ["base"],
+
+ # Data File
+ "data": [
+ 'security/ir.model.access.csv',
+ 'report/dynamic_report.xml',
+ 'views/dynamic_report_configure.xml',
+ ],
+ 'images': [
+ 'static/description/banner_img.png',
+ ],
+
+ # Technical Specif.
+ 'installable': True,
+ 'application': False,
+ 'auto_install': False,
+}
diff --git a/odex30_base/ps_dynamic_report/models/__init__.py b/odex30_base/ps_dynamic_report/models/__init__.py
new file mode 100644
index 0000000..d9bf0a1
--- /dev/null
+++ b/odex30_base/ps_dynamic_report/models/__init__.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8 -*-
+
+from . import dynamic_report_configure
+from . import inherit_ir_actions
diff --git a/odex30_base/ps_dynamic_report/models/dynamic_report_configure.py b/odex30_base/ps_dynamic_report/models/dynamic_report_configure.py
new file mode 100644
index 0000000..05b701a
--- /dev/null
+++ b/odex30_base/ps_dynamic_report/models/dynamic_report_configure.py
@@ -0,0 +1,172 @@
+# -*- coding: utf-8 -*-
+
+from odoo import api, fields, models, _
+from odoo.exceptions import UserError
+
+import xlwt
+import base64
+from io import BytesIO
+
+
+class DynamicReportConfigure(models.Model):
+ _name = 'dynamic.report.configure'
+ _rec_name = 'name'
+
+ name = fields.Char('Name')
+ model_id = fields.Many2one('ir.model', 'Model', domain="[('transient', '=', False)]")
+ dynamic_field_id = fields.One2many('dynamic.report.field', 'dynamic_configure_id', 'Dynamic Field')
+ is_action_created = fields.Boolean('Is Created?', default=False)
+ server_action_id = fields.Many2one('ir.actions.server', 'Server id')
+ report_type = fields.Selection([('pdf', 'PDF'), ('xls', 'XLS')], default='pdf', string="Report Type")
+
+ @api.onchange('model_id')
+ def _onchange_model_id(self):
+ if self.dynamic_field_id:
+ self.dynamic_field_id.unlink()
+
+ def create_dynamic_pdf_report(self, server):
+ server_id = self.env['ir.actions.server'].search([('dynamic_report_id', '=', server)])
+ dynamic_report_id = server_id.dynamic_report_id.dynamic_field_id.filtered(lambda a: a.field_id)
+ Heading_values = [item.field_id.field_description for item in dynamic_report_id]
+
+ record_data = []
+ total_data = []
+ active_model_id = self.env[self._context.get('active_model')].browse(self._context.get('active_ids'))
+ for model in active_model_id:
+ temp = []
+ for item in dynamic_report_id:
+ if item.field_type == 'selection':
+ state = dict(model._fields[item.field_name_id].selection).get(model[item.field_name_id])
+ temp.append(state)
+ elif item.field_type == 'datetime':
+ date = getattr(model, item.field_name_id)
+ temp.append(str(date.date()) if date else '')
+ elif item.field_type == 'date':
+ temp.append(str(getattr(model, item.field_name_id) or ''))
+ elif item.field_type == 'many2one':
+ temp_value = getattr(model, item.field_name_id)
+ value = getattr(temp_value, temp_value._rec_name)
+ temp.append(value)
+ else:
+ temp.append(getattr(model, item.field_name_id))
+
+ if len(total_data) < len(Heading_values):
+ if item.is_sum_calc:
+ m_value = sum(active_model_id.mapped(item.field_name_id))
+ total_data.append(m_value)
+ else:
+ total_data.append('')
+
+ record_data.append(temp)
+ data = {
+ 'report_name': server_id.dynamic_report_id.name,
+ 'model_id': server_id.dynamic_report_id.model_id.model,
+ 'name': server_id.dynamic_report_id.name,
+ 'table_heading': Heading_values,
+ 'record_data': record_data,
+ 'total_data': total_data
+ }
+ if server_id.dynamic_report_id.report_type == 'pdf':
+ return self.env.ref('ps_dynamic_report.action_dynamic_report_print').report_action(self, data=data)
+ else:
+ workbook = xlwt.Workbook(encoding='utf-8', style_compression=0)
+ fl = BytesIO()
+ worksheet = workbook.add_sheet('Report Details', cell_overwrite_ok=True)
+ font = xlwt.Font()
+
+ xlwt.add_palette_colour("custom_colour", 0x21)
+ workbook.set_colour_RGB(0x21, 245, 184, 103)
+ style1 = xlwt.easyxf("pattern: pattern solid, fore_colour custom_colour; alignment: vert centre, horiz center; font: name Arial, bold True;")
+ style2 = xlwt.easyxf("pattern: pattern solid, fore_colour silver_ega; alignment: horizontal center; font: name Arial, bold True;")
+ style3 = xlwt.easyxf('alignment: horizontal center;')
+ style4 = xlwt.easyxf('alignment: horizontal center; font: name Arial, bold True;')
+
+ cell_value = xlwt.XFStyle()
+ cell_value.font = font
+
+ worksheet.write_merge(0, 1, 0, len(Heading_values)-1, server_id.dynamic_report_id.name or '', style1)
+
+ row = 3
+ col = 0
+ for heading in Heading_values:
+ worksheet.col(col).width = 500 * 12
+ worksheet.write(row, col, heading, style2)
+ col += 1
+
+ row = 4
+ col = 0
+ for data in record_data:
+ for rec in data:
+ worksheet.write(row, col, rec, style3)
+ col += 1
+ col = 0
+ row += 1
+
+ col = 0
+ for total in total_data:
+ worksheet.write(row, col, total, style4)
+ col += 1
+
+ filename = server_id.dynamic_report_id.name or "Report Detail"
+ workbook.save(fl)
+ fl.seek(0)
+ test = base64.encodebytes(fl.read())
+ attach_vals = {
+ 'name': '%s.xlsx' % (filename),
+ 'datas': test,
+ }
+ doc_id = self.env['ir.attachment'].create(attach_vals)
+ return {
+ 'type': 'ir.actions.act_url',
+ 'url': 'web/content/%s?download=true' % (doc_id.id),
+ 'target': 'self',
+ }
+
+ def create_server_action(self):
+ if not self.dynamic_field_id:
+ raise UserError(_("Please Select few Fields!!"))
+ vals = {
+ 'name': self.name if self.name else 'Custom Action',
+ 'model_id': self.model_id.id,
+ 'model_name': self.model_id.name,
+ 'state': 'code',
+ 'binding_model_id': self.model_id.id,
+ 'binding_view_types': 'list',
+ 'dynamic_report_id': self.id,
+ 'code': "action = env['dynamic.report.configure'].create_dynamic_pdf_report(server={server_id})".format(server_id=self.id)
+ }
+ server_action_id = self.env['ir.actions.server'].create(vals)
+ self.server_action_id = server_action_id.id
+ self.is_action_created = True
+ return {
+ 'type': 'ir.actions.client',
+ 'tag': 'reload',
+ }
+
+ def remove_server_action(self):
+ if self.is_action_created and self.server_action_id:
+ self.server_action_id.unlink()
+ self.is_action_created = False
+
+
+class DynamicReportField(models.Model):
+ _name = 'dynamic.report.field'
+
+ field_id = fields.Many2one('ir.model.fields', 'Field')
+ sequence = fields.Integer('..', help="Gives the sequence order when displaying a list O2m.")
+ field_name_id = fields.Char(related='field_id.name', string='Target Model Name', readonly=True)
+ field_type = fields.Selection(related='field_id.ttype', string='Field Type')
+ dynamic_configure_id = fields.Many2one('dynamic.report.configure', 'Reference')
+ is_sum_calc = fields.Boolean("Sum")
+
+ @api.model
+ def default_get(self, fields):
+ res = super(DynamicReportField, self).default_get(fields)
+ if self._context:
+ context_keys = self._context.keys()
+ next_sequence = 1
+ if 'dynamic_field_id' in context_keys:
+ if len(self._context.get('dynamic_field_id')) > 0:
+ next_sequence = len(self._context.get('dynamic_field_id')) + 1
+ res.update({'sequence': next_sequence})
+ return res
diff --git a/odex30_base/ps_dynamic_report/models/inherit_ir_actions.py b/odex30_base/ps_dynamic_report/models/inherit_ir_actions.py
new file mode 100644
index 0000000..1691cc8
--- /dev/null
+++ b/odex30_base/ps_dynamic_report/models/inherit_ir_actions.py
@@ -0,0 +1,9 @@
+# -*- coding: utf-8 -*-
+
+from odoo import api, fields, models, _
+
+
+class InheritIrActionsServer(models.Model):
+ _inherit = 'ir.actions.server'
+
+ dynamic_report_id = fields.Many2one('dynamic.report.configure', 'Dynamic Reference')
diff --git a/odex30_base/ps_dynamic_report/report/dynamic_report.xml b/odex30_base/ps_dynamic_report/report/dynamic_report.xml
new file mode 100644
index 0000000..486b8a5
--- /dev/null
+++ b/odex30_base/ps_dynamic_report/report/dynamic_report.xml
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Report
+ dynamic.report.configure
+ qweb-pdf
+ ps_dynamic_report.report_dynamic
+ ps_dynamic_report.report_dynamic
+ report
+
+
+
+
\ No newline at end of file
diff --git a/odex30_base/ps_dynamic_report/security/ir.model.access.csv b/odex30_base/ps_dynamic_report/security/ir.model.access.csv
new file mode 100644
index 0000000..6ff0955
--- /dev/null
+++ b/odex30_base/ps_dynamic_report/security/ir.model.access.csv
@@ -0,0 +1,3 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+access_dynamic_report_configure,dynamic_report_configure,model_dynamic_report_configure,,1,1,1,1
+access_dynamic_report_field,dynamic_report_field,model_dynamic_report_field,,1,1,1,1
diff --git a/odex30_base/ps_dynamic_report/static/description/banner_img.png b/odex30_base/ps_dynamic_report/static/description/banner_img.png
new file mode 100644
index 0000000..44541dc
Binary files /dev/null and b/odex30_base/ps_dynamic_report/static/description/banner_img.png differ
diff --git a/odex30_base/ps_dynamic_report/static/description/icon.png b/odex30_base/ps_dynamic_report/static/description/icon.png
new file mode 100644
index 0000000..4754100
Binary files /dev/null and b/odex30_base/ps_dynamic_report/static/description/icon.png differ
diff --git a/odex30_base/ps_dynamic_report/static/description/images/gmail.png b/odex30_base/ps_dynamic_report/static/description/images/gmail.png
new file mode 100644
index 0000000..689c36d
Binary files /dev/null and b/odex30_base/ps_dynamic_report/static/description/images/gmail.png differ
diff --git a/odex30_base/ps_dynamic_report/static/description/images/logo.jpeg b/odex30_base/ps_dynamic_report/static/description/images/logo.jpeg
new file mode 100644
index 0000000..a07b2c1
Binary files /dev/null and b/odex30_base/ps_dynamic_report/static/description/images/logo.jpeg differ
diff --git a/odex30_base/ps_dynamic_report/static/description/images/ps_image1.png b/odex30_base/ps_dynamic_report/static/description/images/ps_image1.png
new file mode 100644
index 0000000..d6f7fbd
Binary files /dev/null and b/odex30_base/ps_dynamic_report/static/description/images/ps_image1.png differ
diff --git a/odex30_base/ps_dynamic_report/static/description/images/ps_image2.png b/odex30_base/ps_dynamic_report/static/description/images/ps_image2.png
new file mode 100644
index 0000000..1a86f98
Binary files /dev/null and b/odex30_base/ps_dynamic_report/static/description/images/ps_image2.png differ
diff --git a/odex30_base/ps_dynamic_report/static/description/images/ps_image3.png b/odex30_base/ps_dynamic_report/static/description/images/ps_image3.png
new file mode 100644
index 0000000..9afafb2
Binary files /dev/null and b/odex30_base/ps_dynamic_report/static/description/images/ps_image3.png differ
diff --git a/odex30_base/ps_dynamic_report/static/description/images/ps_image4.png b/odex30_base/ps_dynamic_report/static/description/images/ps_image4.png
new file mode 100644
index 0000000..cf3f76b
Binary files /dev/null and b/odex30_base/ps_dynamic_report/static/description/images/ps_image4.png differ
diff --git a/odex30_base/ps_dynamic_report/static/description/images/ps_image5.png b/odex30_base/ps_dynamic_report/static/description/images/ps_image5.png
new file mode 100644
index 0000000..db0d76d
Binary files /dev/null and b/odex30_base/ps_dynamic_report/static/description/images/ps_image5.png differ
diff --git a/odex30_base/ps_dynamic_report/static/description/images/ps_image6.png b/odex30_base/ps_dynamic_report/static/description/images/ps_image6.png
new file mode 100644
index 0000000..b2a0cf8
Binary files /dev/null and b/odex30_base/ps_dynamic_report/static/description/images/ps_image6.png differ
diff --git a/odex30_base/ps_dynamic_report/static/description/images/ps_image7.png b/odex30_base/ps_dynamic_report/static/description/images/ps_image7.png
new file mode 100644
index 0000000..d235b50
Binary files /dev/null and b/odex30_base/ps_dynamic_report/static/description/images/ps_image7.png differ
diff --git a/odex30_base/ps_dynamic_report/static/description/images/ps_image8.png b/odex30_base/ps_dynamic_report/static/description/images/ps_image8.png
new file mode 100644
index 0000000..5509a6a
Binary files /dev/null and b/odex30_base/ps_dynamic_report/static/description/images/ps_image8.png differ
diff --git a/odex30_base/ps_dynamic_report/static/description/images/web.png b/odex30_base/ps_dynamic_report/static/description/images/web.png
new file mode 100644
index 0000000..ebc528d
Binary files /dev/null and b/odex30_base/ps_dynamic_report/static/description/images/web.png differ
diff --git a/odex30_base/ps_dynamic_report/static/description/images/whatsapp.png b/odex30_base/ps_dynamic_report/static/description/images/whatsapp.png
new file mode 100644
index 0000000..a8d0a8c
Binary files /dev/null and b/odex30_base/ps_dynamic_report/static/description/images/whatsapp.png differ
diff --git a/odex30_base/ps_dynamic_report/static/description/index.html b/odex30_base/ps_dynamic_report/static/description/index.html
new file mode 100644
index 0000000..92fd66a
--- /dev/null
+++ b/odex30_base/ps_dynamic_report/static/description/index.html
@@ -0,0 +1,230 @@
+
+
+
+
+
+
+
+
+
+
+ Hello, web
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Community
+
+
+ Enterprise
+
+
+
+
+
+
+
+
+
+
+ This Module helps you to create Fully Dynamically Pdf & XLS report. You Can also Create Multiple
+ Action of Same Model and Select Fields according to Show in Report Just one Click.
+
+
+
+
+
+
+
+
+
+
+
+
+
Go to Dynamic Report Configure under(settings)
+
+
+
+
+
+
+
+
+
+
+
+
+
Create a one
+ record
+
+ Select the model which you want to create of his Server action
+ Choose a Report Type PDF or XLS
+ And if you want a total of any fields, Just enable a Sum checkbox.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Click on Create Action Button to create a server
+ action.
+
+
+
+
+
+
+
+
+
+
+
Above you can see a action is created. Now, Click on it
+ to Download Report
+
+
+
+
+
+
+
+
+
+
+
Pdf report.
+
+
+
+
+
+
+
+
+
+
+
To Create a XLS report action.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Xls Report
+
+
+
+
+
+
+
+
+
+
+
+ HELP AND SUPPORT
+
+
+
+
+
+
+
+
+
Write a mail to us
+
+
+
+
+
+
+
Write a text To us on WhatsApp
+
+
+
+
+
+
+
Visit Our Wesite
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/odex30_base/ps_dynamic_report/views/dynamic_report_configure.xml b/odex30_base/ps_dynamic_report/views/dynamic_report_configure.xml
new file mode 100644
index 0000000..d29434d
--- /dev/null
+++ b/odex30_base/ps_dynamic_report/views/dynamic_report_configure.xml
@@ -0,0 +1,83 @@
+
+
+
+ dynamic.report.configure.view.form
+ dynamic.report.configure
+
+
+
+
+
+
+ dynamic.report.configure.view.tree
+ dynamic.report.configure
+
+
+
+
+
+
+
+
+
+ Dynamic Report
+ ir.actions.act_window
+ dynamic.report.configure
+ list,form
+
+
+
+
diff --git a/odex30_base/resource_booking/README.rst b/odex30_base/resource_booking/README.rst
new file mode 100644
index 0000000..6af59bc
--- /dev/null
+++ b/odex30_base/resource_booking/README.rst
@@ -0,0 +1,223 @@
+================
+Resource booking
+================
+
+..
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ !! This file is generated by oca-gen-addon-readme !!
+ !! changes will be overwritten. !!
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ !! source digest: sha256:c9c94fe5f0781ebe30b15603ca61481b52714b5274677b4e0eb7c1d919831921
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+.. |badge1| image:: https://img.shields.io/badge/maturity-Production%2FStable-green.png
+ :target: https://odoo-community.org/page/development-status
+ :alt: Production/Stable
+.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
+ :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
+ :alt: License: AGPL-3
+.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fcalendar-lightgray.png?logo=github
+ :target: https://github.com/OCA/calendar/tree/14.0/resource_booking
+ :alt: OCA/calendar
+.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
+ :target: https://translation.odoo-community.org/projects/calendar-14-0/calendar-14-0-resource_booking
+ :alt: Translate me on Weblate
+.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
+ :target: https://runboat.odoo-community.org/builds?repo=OCA/calendar&target_branch=14.0
+ :alt: Try me on Runboat
+
+|badge1| |badge2| |badge3| |badge4| |badge5|
+
+This module adds a new app to allow you to book resource combinations in given
+schedules.
+
+Example use cases:
+
+* Management of consultations in a clinic.
+* Salesman appointments.
+* Classroom and projector reservations.
+* Hotel room booking.
+
+Among the things you can do:
+
+* Specify the type of booking, which includes a calendar of availability.
+* Specify which resources can be booked together. All of them must be free to be booked.
+* Place pending bookings, effectively giving permissions to someone to see the availability calendar and choose one slot.
+* Partners can do that from their portals.
+* If a partner has no user, he can still do the same via a tokenized URL.
+* Backend users can also do that from the backend.
+* Booking lifecycle with computed states.
+* Automatic meeting creation and deletion.
+* Automatic conflict detection.
+* Deadline to block modifications.
+
+**Table of contents**
+
+.. contents::
+ :local:
+
+Installation
+============
+
+To install this module, you need to install these dependencies:
+
+#. `freezegun `__
+#. `web_calendar_slot_duration `__
+
+When someone is a manager, he will have access to *Resource Bookings >
+Configuration*, where he will be able to configure resources, leaves and
+schedules. This menu is just provided as a shortcut. However, if you want to
+manage that stuff more comfortably:
+
+* To manage human resources, install `hr `__.
+* To manage their leaves, install `hr_holidays `__.
+* To manage work centers, install `mrp `__.
+
+Configuration
+=============
+
+To let some backend user to book resources:
+
+#. Go to *Settings > Users & Companies > Users*.
+#. Pick or create one.
+#. Assign *Resource Booking > User*.
+
+To let some backend user to configure types and combinations, and to be able to
+modify overdue bookings:
+
+#. Go to *Settings > Users & Companies > Users*.
+#. Pick or create one.
+#. Assign *Resource Booking > Manager*.
+
+To configure one booking type:
+
+#. Go to *Resource Bookings > Types*.
+#. Create one.
+#. Give it a *name*.
+#. Set the *Duration*, to know the time assigned to each calendar slot. It will
+ also be the default duration for each booking, although that can be changed
+ later if necessary.
+#. Set the *Modifications Deadline*, to forbid non-managers to alter dates of
+ a booking when it's too late.
+#. Choose one *Availability Calendar*. No bookings will exist outside of it.
+#. Under *Meeting defaults*, you will be able to fill some values that will
+ be used by default on calendar meetings. These will appear in the global
+ calendar when some booking is reserved.
+#. Choose some *Available resource combinations*. All combinations in the same
+ line must be free to be booked together; otherwise the booking will not be
+ able to be scheduled. You can sort them.
+#. Pick up one *Combination Assignment*. If you choose *Sorted*, then the order
+ of the combinations you chose will indicate the one that is selected first.
+ Of course, it must be free to be selected.
+#. Save.
+
+Usage
+=====
+
+This module installs a new app, "Resource bookings".
+
+Bookings may involve you:
+
+* Maybe because you requested to book something.
+* Maybe because you are one of the booked resources, if a booking represents
+ some kind of appointment.
+
+To see which bookings involve you:
+
+#. Go to *Resource Bookings > Bookings*.
+#. You can switch to the list view if you need to see also the pending ones.
+#. You can remove the "Involving me" filter if you want to see others' bookings.
+
+To book some resources:
+
+#. Go to *Resource Bookings > Types*.
+#. Pick the type of booking you want.
+#. Click on *Booking Count*.
+#. Click on a free slot.
+#. Fill the *Requester*, which may or not be yourself.
+#. Uncheck *Auto assign* and pick one *Resources combination*, in case the one
+ assigned automatically isn't the one you want.
+
+To invite someone to book a resource combination from the portal:
+
+#. Go to *Resource Bookings > Types*.
+#. Pick the type of booking you want.
+#. Click on *Booking Count*.
+#. Click on the list view icon.
+#. Click on *Create*.
+#. Fill the *Requester*.
+#. Uncheck *Auto assign* and pick one *Resources combination*, if you want that
+ the requester is assigned to that combination. Otherwise, leave it empty,
+ and some free combination will be assigned automatically when the requester
+ picks a free slot.
+#. Choose the *duration*, in case it is different from the one specified in the
+ resource booking type.
+#. Click on *Share > Send*.
+#. The requester will receive an email to select a calendar slot from his portal.
+
+Known issues / Roadmap
+======================
+
+* Allow combination auto-assignment based on least used combination.
+* Allow customer to choose combination.
+* Some error messages would be a bit more helpful if they specify the schedule
+ impossibility reason, but that should be done without affecting performance.
+* Optimize ``_calendar_event_busy_intervals()`` to make it work in batch.
+
+Changelog
+=========
+
+14.0.1.3.2 (2023-08-28)
+~~~~~~~~~~~~~~~~~~~~~~~
+
+**Features**
+
+- Bookings can now span more than one calendar day. (`#77 `_)
+
+Bug Tracker
+===========
+
+Bugs are tracked on `GitHub Issues `_.
+In case of trouble, please check there if your issue has already been reported.
+If you spotted it first, help us to smash it by providing a detailed and welcomed
+`feedback `_.
+
+Do not contact contributors directly about support or help with technical issues.
+
+Credits
+=======
+
+Authors
+~~~~~~~
+
+* Tecnativa
+
+Contributors
+~~~~~~~~~~~~
+
+* Jairo Llopis (https://www.tecnativa.com/)
+
+Maintainers
+~~~~~~~~~~~
+
+This module is maintained by the OCA.
+
+.. image:: https://odoo-community.org/logo.png
+ :alt: Odoo Community Association
+ :target: https://odoo-community.org
+
+OCA, or the Odoo Community Association, is a nonprofit organization whose
+mission is to support the collaborative development of Odoo features and
+promote its widespread use.
+
+.. |maintainer-pedrobaeza| image:: https://github.com/pedrobaeza.png?size=40px
+ :target: https://github.com/pedrobaeza
+ :alt: pedrobaeza
+
+Current `maintainer `__:
+
+|maintainer-pedrobaeza|
+
+This module is part of the `OCA/calendar `_ project on GitHub.
+
+You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
diff --git a/odex30_base/resource_booking/__init__.py b/odex30_base/resource_booking/__init__.py
new file mode 100644
index 0000000..f7209b1
--- /dev/null
+++ b/odex30_base/resource_booking/__init__.py
@@ -0,0 +1,2 @@
+from . import models
+from . import controllers
diff --git a/odex30_base/resource_booking/__manifest__.py b/odex30_base/resource_booking/__manifest__.py
new file mode 100644
index 0000000..c4df8e9
--- /dev/null
+++ b/odex30_base/resource_booking/__manifest__.py
@@ -0,0 +1,49 @@
+# Copyright 2021 Tecnativa - Jairo Llopis
+# Copyright 2022 Tecnativa - Pedro M. Baeza
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
+
+{
+ "name": "Resource booking",
+ "summary": "Manage appointments and resource booking",
+ "version": "18.0.1.0.0",
+ "development_status": "Production/Stable",
+ "category": "Appointments",
+ "website": "https://github.com/OCA/calendar",
+ "author": "Tecnativa, Odoo Community Association (OCA)",
+ "maintainers": ["pedrobaeza"],
+ "license": "AGPL-3",
+ "application": True,
+ "installable": True,
+ "external_dependencies": {
+ "python": [
+ # Used implicitly
+ "cssselect",
+ ],
+ },
+ "depends": [
+ "calendar",
+ "mail",
+ "portal",
+ "resource",
+ "web_calendar_slot_duration",
+ ],
+ "data": [
+ "data/mail.xml",
+ "security/resource_booking_security.xml",
+ "security/ir.model.access.csv",
+ "templates/assets.xml",
+ "templates/portal.xml",
+ "views/calendar_event_views.xml",
+ "views/resource_booking_combination_views.xml",
+ "views/resource_booking_type_views.xml",
+ "views/resource_booking_views.xml",
+ "views/menus.xml",
+ ],
+ "demo": ["demo/res_users_demo.xml"],
+ 'assets': {
+ 'web.assets_frontend': [
+ 'resource_booking/static/src/css/portal.scss',
+ ],
+ }
+
+}
diff --git a/odex30_base/resource_booking/controllers/__init__.py b/odex30_base/resource_booking/controllers/__init__.py
new file mode 100644
index 0000000..8c3feb6
--- /dev/null
+++ b/odex30_base/resource_booking/controllers/__init__.py
@@ -0,0 +1 @@
+from . import portal
diff --git a/odex30_base/resource_booking/controllers/portal.py b/odex30_base/resource_booking/controllers/portal.py
new file mode 100644
index 0000000..827afb1
--- /dev/null
+++ b/odex30_base/resource_booking/controllers/portal.py
@@ -0,0 +1,142 @@
+# Copyright 2021 Tecnativa - Jairo Llopis
+# Copyright 2022 Tecnativa - Pedro M. Baeza
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
+
+from datetime import datetime
+from urllib.parse import quote_plus
+
+from dateutil.parser import isoparse
+
+from odoo.exceptions import AccessError, MissingError, ValidationError
+from odoo.http import request, route
+
+from odoo.addons.portal.controllers import portal
+
+
+class CustomerPortal(portal.CustomerPortal):
+ def _get_booking_sudo(self, booking_id, access_token):
+ """Get sudoed booking record from its ID."""
+ booking_sudo = self._document_check_access(
+ "resource.booking", booking_id, access_token
+ )
+ return booking_sudo.with_context(
+ using_portal=True, tz=booking_sudo.type_id.resource_calendar_id.tz
+ )
+
+ def _prepare_portal_layout_values(self):
+ """Compute values for multi-booking portal views."""
+ values = super(CustomerPortal, self)._prepare_portal_layout_values()
+ booking_count = request.env["resource.booking"].search_count([])
+ values.update({"booking_count": booking_count})
+ return values
+
+ def _booking_get_page_view_values(self, booking_sudo, access_token, **kwargs):
+ """Compute values for single-booking portal views."""
+ return self._get_page_view_values(
+ booking_sudo,
+ access_token,
+ {"page_name": "booking", "booking_sudo": booking_sudo},
+ "my_bookings_history",
+ False,
+ **kwargs
+ )
+
+ @route(
+ ["/my/bookings", "/my/bookings/page/"],
+ auth="user",
+ type="http",
+ website=True,
+ )
+ def portal_my_bookings(self, page=1, **kwargs):
+ """List bookings that I can access."""
+ Booking = request.env["resource.booking"].with_context(using_portal=True)
+ values = self._prepare_portal_layout_values()
+ pager = portal.pager(
+ url="/my/bookings",
+ total=values["booking_count"],
+ page=page,
+ step=self._items_per_page,
+ )
+ bookings = Booking.search(
+ [], limit=self._items_per_page, offset=pager["offset"]
+ )
+ request.session["my_bookings_history"] = bookings.ids
+ values.update({"bookings": bookings, "pager": pager, "page_name": "bookings"})
+ return request.render("resource_booking.portal_my_bookings", values)
+
+ @route(["/my/bookings/"], type="http", auth="public", website=True)
+ def portal_booking_page(self, booking_id, access_token=None, **kwargs):
+ """Portal booking form."""
+ try:
+ booking_sudo = self._get_booking_sudo(booking_id, access_token)
+ except (AccessError, MissingError):
+ return request.redirect("/my")
+ # ensure attachment are accessible with access token inside template
+ for attachment in booking_sudo.mapped("message_ids.attachment_ids"):
+ attachment.generate_access_token()
+ values = self._booking_get_page_view_values(
+ booking_sudo, access_token, **kwargs
+ )
+ return request.render("resource_booking.resource_booking_portal_form", values)
+
+ @route(
+ [
+ "/my/bookings//schedule",
+ "/my/bookings//schedule//",
+ ],
+ auth="public",
+ type="http",
+ website=True,
+ )
+ def portal_booking_schedule(
+ self, booking_id, access_token=None, year=None, month=None, error=None, **kwargs
+ ):
+ """Portal booking scheduling."""
+ try:
+ booking_sudo = self._get_booking_sudo(booking_id, access_token)
+ except (AccessError, MissingError):
+ return request.redirect("/my")
+ values = self._booking_get_page_view_values(
+ booking_sudo, access_token, **kwargs
+ )
+ values.update(booking_sudo._get_calendar_context(year, month))
+ values.update({"error": error, "page_name": "booking_schedule"})
+ return request.render(
+ "resource_booking.resource_booking_portal_schedule", values
+ )
+
+ @route(
+ ["/my/bookings//cancel"],
+ auth="public",
+ type="http",
+ website=True,
+ )
+ def portal_booking_cancel(self, booking_id, access_token=None, **kwargs):
+ """Cancel the booking."""
+ booking_sudo = self._get_booking_sudo(booking_id, access_token)
+ booking_sudo.action_cancel()
+ return request.redirect("/my")
+
+ @route(
+ ["/my/bookings//confirm"],
+ auth="public",
+ type="http",
+ website=True,
+ )
+ def portal_booking_confirm(self, booking_id, access_token, when, **kwargs):
+ """Confirm a booking in a given datetime."""
+ booking_sudo = self._get_booking_sudo(booking_id, access_token)
+ when_tz_aware = isoparse(when)
+ when_naive = datetime.utcfromtimestamp(when_tz_aware.timestamp())
+ try:
+ booking_sudo.sudo().write({'start': when_naive})
+ # with Form(booking_sudo) as booking_form:
+ # booking_form.start = when_naive
+ except ValidationError as error:
+ url = booking_sudo.get_portal_url(
+ suffix="/schedule/{:%Y/%m}".format(when_tz_aware),
+ query_string="&error={}".format(quote_plus(error.name)),
+ )
+ return request.redirect(url)
+ booking_sudo.action_confirm()
+ return request.redirect(booking_sudo.get_portal_url())
diff --git a/odex30_base/resource_booking/data/mail.xml b/odex30_base/resource_booking/data/mail.xml
new file mode 100644
index 0000000..d3bfd16
--- /dev/null
+++ b/odex30_base/resource_booking/data/mail.xml
@@ -0,0 +1,28 @@
+
+
+