From 44d878698a0218af788d9e17872bf9434368c4de Mon Sep 17 00:00:00 2001 From: "Laurent Mignon (ACSONE)" Date: Thu, 19 Mar 2026 10:50:33 +0100 Subject: [PATCH 1/7] [IMP] simplify tests --- fs_file/tests/test_fs_file.py | 12 ++++++------ fs_folder/tests/common.py | 10 +++++----- fs_image/tests/test_fs_image.py | 12 ++++++------ storage_thumbnail/tests/test_thumbnail.py | 16 ++++------------ 4 files changed, 21 insertions(+), 29 deletions(-) diff --git a/fs_file/tests/test_fs_file.py b/fs_file/tests/test_fs_file.py index 0e6e02c66a..bcdfcce19d 100644 --- a/fs_file/tests/test_fs_file.py +++ b/fs_file/tests/test_fs_file.py @@ -23,6 +23,7 @@ def setUpClass(cls): cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True)) cls.loader = FakeModelLoader(cls.env, cls.__module__) cls.loader.backup_registry() + cls.addClassCleanup(cls.loader.restore_registry) from .models import TestModel cls.loader.update_registry((TestModel,)) @@ -38,13 +39,13 @@ def setUpClass(cls): f.seek(0) cls.png_content = f + def check_attrs(self): + # Deactivate check_attrs to avoid conflict with FakeModelLoader. + # since superClass uses it for its own puposes not relevant for our tests. + pass + def setUp(self): super().setUp() - # Remove check_attrs cleanup if exists to avoid conflict with FakeModelLoader. - # since superClass uses it for its own puposes not relevant for our tests. - check_attrs = (getattr(self, "check_attrs", None), tuple(), {}) - if check_attrs in self._cleanups: - self._cleanups.remove(check_attrs) self.temp_dir: FSStorage = self.env["fs.storage"].create( { "name": "Temp FS Storage", @@ -59,7 +60,6 @@ def setUp(self): def tearDownClass(cls): if os.path.exists(cls.tmpfile_path): os.remove(cls.tmpfile_path) - cls.loader.restore_registry() return super().tearDownClass() def _test_create(self, fs_file_value): diff --git a/fs_folder/tests/common.py b/fs_folder/tests/common.py index eb8cdf0286..86204960a3 100644 --- a/fs_folder/tests/common.py +++ b/fs_folder/tests/common.py @@ -46,13 +46,13 @@ def setUpClass(cls): def cleanup_tempdir(): shutil.rmtree(cls.temp_dir) + def check_attrs(self): + # Deactivate check_attrs to avoid conflict with FakeModelLoader. + # since superClass uses it for its own puposes not relevant for our tests. + pass + def setUp(self): super().setUp() - # Remove check_attrs cleanup if exists to avoid conflict with FakeModelLoader. - # since superClass uses it for its own puposes not relevant for our tests. - check_attrs = (getattr(self, "check_attrs", None), tuple(), {}) - if check_attrs in self._cleanups: - self._cleanups.remove(check_attrs) # enforce temp_backend field since it seems that they are reset on # savepoint rollback when managed by server_environment -> TO Be investigated self.temp_backend.write( diff --git a/fs_image/tests/test_fs_image.py b/fs_image/tests/test_fs_image.py index bf4c7352f5..08c2614aa4 100644 --- a/fs_image/tests/test_fs_image.py +++ b/fs_image/tests/test_fs_image.py @@ -26,6 +26,7 @@ def setUpClass(cls): ) cls.loader = FakeModelLoader(cls.env, cls.__module__) cls.loader.backup_registry() + cls.addClassCleanup(cls.loader.restore_registry) from .models import TestImageModel, TestRelatedImageModel cls.loader.update_registry((TestImageModel, TestRelatedImageModel)) @@ -40,13 +41,13 @@ def setUpClass(cls): f.write(cls.create_content) cls.filename = os.path.basename(cls.tmpfile_path) + def check_attrs(self): + # Deactivate check_attrs to avoid conflict with FakeModelLoader. + # since superClass uses it for its own puposes not relevant for our tests. + pass + def setUp(self): super().setUp() - # Remove check_attrs cleanup if exists to avoid conflict with FakeModelLoader. - # since superClass uses it for its own puposes not relevant for our tests. - check_attrs = (getattr(self, "check_attrs", None), tuple(), {}) - if check_attrs in self._cleanups: - self._cleanups.remove(check_attrs) self.temp_dir: FSStorage = self.env["fs.storage"].create( { "name": "Temp FS Storage", @@ -61,7 +62,6 @@ def setUp(self): def tearDownClass(cls): if os.path.exists(cls.tmpfile_path): os.remove(cls.tmpfile_path) - cls.loader.restore_registry() return super().tearDownClass() @classmethod diff --git a/storage_thumbnail/tests/test_thumbnail.py b/storage_thumbnail/tests/test_thumbnail.py index 954cced924..29e17bc3fc 100644 --- a/storage_thumbnail/tests/test_thumbnail.py +++ b/storage_thumbnail/tests/test_thumbnail.py @@ -14,6 +14,7 @@ def setUpClass(cls): res = super().setUpClass() cls.loader = FakeModelLoader(cls.env, cls.__module__) cls.loader.backup_registry() + cls.addClassCleanup(cls.loader.restore_registry) from .models import ModelTest cls.loader.update_registry((ModelTest,)) @@ -25,19 +26,10 @@ def setUpClass(cls): cls.filename = "akretion-logo.png" return res - def setUp(self): - res = super().setUp() - # Remove check_attrs cleanup if exists to avoid conflict with FakeModelLoader. + def check_attrs(self): + # Deactivate check_attrs to avoid conflict with FakeModelLoader. # since superClass uses it for its own puposes not relevant for our tests. - check_attrs = (getattr(self, "check_attrs", None), tuple(), {}) - if check_attrs in self._cleanups: - self._cleanups.remove(check_attrs) - return res - - @classmethod - def tearDownClass(cls): - cls.loader.restore_registry() - return super().tearDownClass() + pass def _create_thumbnail(self): # create thumbnail From 5cb619f4501b79bf9b82f017d0214ff5a46a2f4e Mon Sep 17 00:00:00 2001 From: "Laurent Mignon (ACSONE)" Date: Wed, 18 Mar 2026 16:41:12 +0100 Subject: [PATCH 2/7] [IMP]fs_storage: Prevent updates from safe_eval --- fs_storage/models/fs_storage.py | 45 +++++++++++++++++++++++++ fs_storage/tests/test_fs_storage.py | 51 ++++++++++++++++++++++++++++- 2 files changed, 95 insertions(+), 1 deletion(-) diff --git a/fs_storage/models/fs_storage.py b/fs_storage/models/fs_storage.py index b36a0dbbab..0cc243ce89 100644 --- a/fs_storage/models/fs_storage.py +++ b/fs_storage/models/fs_storage.py @@ -61,6 +61,32 @@ def new_func1(*args, **kwargs): return decorator +def prevent_call_from_safe_eval(reason): + """Decorator to prevent the call to the method in the context of a + safe_eval. + """ + + def deorator(func): + @functools.wraps(func) + def wrapper(self, *args, **kwargs): + for frame_info in inspect.stack(): + filename = frame_info.filename or "" + function = frame_info.function or "" + if "safe_eval" in filename or function == "safe_eval": + raise ValidationError( + _( + "Calling fs.storage.%(reason)s is not allowed " + "in a safe_eval context.", + reason=reason, + ) + ) + return func(self, *args, **kwargs) + + return wrapper + + return deorator + + class FSStorage(models.Model): _name = "fs.storage" _inherit = "server.env.mixin" @@ -288,11 +314,30 @@ def _server_env_fields(self): "check_connection_method": {}, } + @api.model_create_multi + @prevent_call_from_safe_eval("create") + def create(self, vals_list): + return super().create(vals_list) + + @prevent_call_from_safe_eval("create") + def _create(self, data_list): + return super()._create(data_list) + + @prevent_call_from_safe_eval("write") def write(self, vals): self.__fs = None self.env.registry.clear_cache() return super().write(vals) + @prevent_call_from_safe_eval("write") + def _write(self, vals): + return super()._write(vals) + + @api.ondelete(at_uninstall=False) + @prevent_call_from_safe_eval("unlink") + def _check_no_safe_eval_call(self): + pass + def get_directory_path(self): """Returns directory path with substitution done.""" return ( diff --git a/fs_storage/tests/test_fs_storage.py b/fs_storage/tests/test_fs_storage.py index 4e72cec8dc..3c42e4fbe8 100644 --- a/fs_storage/tests/test_fs_storage.py +++ b/fs_storage/tests/test_fs_storage.py @@ -5,7 +5,7 @@ from odoo.exceptions import ValidationError from odoo.tests import Form -from odoo.tools import mute_logger +from odoo.tools import mute_logger, safe_eval from .common import TestFSStorageCase @@ -246,3 +246,52 @@ def test_directory_path_substitution(self): self.backend.directory_path = template # Assert different (db name should be replaced) self.assertNotEqual(template, self.backend.get_directory_path()) + + def test_no_create_in_safe_eval(self): + # check that we can't create a file in safe_eval + with self.assertRaisesRegex( + ValidationError, + "Calling fs.storage.create is not allowed in a safe_eval context.", + ): + safe_eval.safe_eval( + "env['fs.storage'].create({'name': 'test', 'code': 'test'})", + {"env": self.env}, + ) + + with self.assertRaisesRegex( + ValidationError, + "Calling fs.storage.create is not allowed in a safe_eval context.", + ): + safe_eval.safe_eval( + "env['fs.storage']._create({'name': 'test', 'code': 'test'})", + {"env": self.env}, + ) + + def test_no_write_in_safe_eval(self): + # check that we can't write a file in safe_eval + with self.assertRaisesRegex( + ValidationError, + "Calling fs.storage.write is not allowed in a safe_eval context.", + ): + safe_eval.safe_eval( + "env['fs.storage'].search([]).write({'name': 'test'})", + {"env": self.env}, + ) + with self.assertRaisesRegex( + ValidationError, + "Calling fs.storage.write is not allowed in a safe_eval context.", + ): + safe_eval.safe_eval( + "env['fs.storage'].search([])._write({'name': 'test'})", + {"env": self.env}, + ) + + def test_no_unlink_in_safe_eval(self): + # check that we can't unlink a file in safe_eval + with self.assertRaisesRegex( + ValidationError, + "Calling fs.storage.unlink is not allowed in a safe_eval context.", + ): + safe_eval.safe_eval( + "env['fs.storage'].search([]).unlink()", {"env": self.env} + ) From fe28f8e6fc21097643f5337128fa43c5b6737ca1 Mon Sep 17 00:00:00 2001 From: "Laurent Mignon (ACSONE)" Date: Thu, 19 Mar 2026 16:02:47 +0100 Subject: [PATCH 3/7] [IMP]fs_storage: Prevent updates from safe_eval in Odoo 18.0 --- fs_storage/models/fs_storage.py | 4 ++-- fs_storage/tests/test_fs_storage.py | 9 +++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/fs_storage/models/fs_storage.py b/fs_storage/models/fs_storage.py index 0cc243ce89..0e60422123 100644 --- a/fs_storage/models/fs_storage.py +++ b/fs_storage/models/fs_storage.py @@ -330,8 +330,8 @@ def write(self, vals): return super().write(vals) @prevent_call_from_safe_eval("write") - def _write(self, vals): - return super()._write(vals) + def _write_multi(self, vals_list): + return super()._write_multi(vals_list) @api.ondelete(at_uninstall=False) @prevent_call_from_safe_eval("unlink") diff --git a/fs_storage/tests/test_fs_storage.py b/fs_storage/tests/test_fs_storage.py index 3c42e4fbe8..631ce4f250 100644 --- a/fs_storage/tests/test_fs_storage.py +++ b/fs_storage/tests/test_fs_storage.py @@ -286,6 +286,15 @@ def test_no_write_in_safe_eval(self): {"env": self.env}, ) + with self.assertRaisesRegex( + ValidationError, + "Calling fs.storage.write is not allowed in a safe_eval context.", + ): + safe_eval.safe_eval( + "env['fs.storage'].search([])._write_multi([{'name': 'test'}])", + {"env": self.env}, + ) + def test_no_unlink_in_safe_eval(self): # check that we can't unlink a file in safe_eval with self.assertRaisesRegex( From 13191577f8df33f7f4fa6dda94b0f4ba9cdb3246 Mon Sep 17 00:00:00 2001 From: oca-ci Date: Thu, 19 Mar 2026 15:25:57 +0000 Subject: [PATCH 4/7] [UPD] Update fs_storage.pot --- fs_storage/i18n/fs_storage.pot | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fs_storage/i18n/fs_storage.pot b/fs_storage/i18n/fs_storage.pot index 535ee608f4..49730a23c3 100644 --- a/fs_storage/i18n/fs_storage.pot +++ b/fs_storage/i18n/fs_storage.pot @@ -23,6 +23,12 @@ msgstr "" msgid "Available properties" msgstr "" +#. module: fs_storage +#. odoo-python +#: code:addons/fs_storage/models/fs_storage.py:0 +msgid "Calling fs.storage.%(reason)s is not allowed in a safe_eval context." +msgstr "" + #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__check_connection_method #: model:ir.model.fields,field_description:fs_storage.field_fs_test_connection__check_connection_method From 5e7a8f6200788c388524d1e227b58ea88a08e833 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Thu, 19 Mar 2026 15:29:44 +0000 Subject: [PATCH 5/7] [BOT] post-merge updates --- README.md | 2 +- fs_storage/README.rst | 2 +- fs_storage/__manifest__.py | 2 +- fs_storage/static/description/index.html | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index f8015efae5..1c65bcb85e 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ addon | version | maintainers | summary [fs_folder_ms_drive](fs_folder_ms_drive/) | 18.0.2.0.0 | lmignon | Display and manage your files from Microsoft drives from within Odoo [fs_folder_webdav](fs_folder_webdav/) | 18.0.1.0.0 | jguenat | UI improvement when managing WebDAV folder [fs_image](fs_image/) | 18.0.1.0.0 | lmignon | Field to store images into filesystem storages -[fs_storage](fs_storage/) | 18.0.2.1.1 | | Implement the concept of Storage with amazon S3, sftp... +[fs_storage](fs_storage/) | 18.0.2.1.2 | | Implement the concept of Storage with amazon S3, sftp... [fs_storage_ms_drive](fs_storage_ms_drive/) | 18.0.2.0.0 | lmignon | Add the microsoft drives (OneDrive, Sharepoint) as a storage backend [image_tag](image_tag/) | 18.0.1.0.0 | | Image tag model [microsoft_drive_account](microsoft_drive_account/) | 18.0.2.0.0 | lmignon | Link user with Microsoft diff --git a/fs_storage/README.rst b/fs_storage/README.rst index 151eaacbec..4cdae5cb19 100644 --- a/fs_storage/README.rst +++ b/fs_storage/README.rst @@ -11,7 +11,7 @@ Filesystem Storage Backend !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:56e35c5816f37443d3bfb1ac7d6ebd4451e7b8c6e3d7c94a0f176f2b7d38b520 + !! source digest: sha256:b12a9e0e041121ef9301a2e54de2547c3a8a49408067c074b4fdfea8e5d0d74c !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png diff --git a/fs_storage/__manifest__.py b/fs_storage/__manifest__.py index 6d713a97ea..129a3f3626 100644 --- a/fs_storage/__manifest__.py +++ b/fs_storage/__manifest__.py @@ -5,7 +5,7 @@ { "name": "Filesystem Storage Backend", "summary": "Implement the concept of Storage with amazon S3, sftp...", - "version": "18.0.2.1.1", + "version": "18.0.2.1.2", "category": "FS Storage", "website": "https://github.com/OCA/storage", "author": " ACSONE SA/NV, Odoo Community Association (OCA)", diff --git a/fs_storage/static/description/index.html b/fs_storage/static/description/index.html index b54e96619f..3104d3767c 100644 --- a/fs_storage/static/description/index.html +++ b/fs_storage/static/description/index.html @@ -372,7 +372,7 @@

Filesystem Storage Backend

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! source digest: sha256:56e35c5816f37443d3bfb1ac7d6ebd4451e7b8c6e3d7c94a0f176f2b7d38b520 +!! source digest: sha256:b12a9e0e041121ef9301a2e54de2547c3a8a49408067c074b4fdfea8e5d0d74c !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

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

This addon is a technical addon that allows you to define filesystem From ccf4b7ddca590f039ee86673e4a46b646f90599d Mon Sep 17 00:00:00 2001 From: Weblate Date: Thu, 19 Mar 2026 15:29:53 +0000 Subject: [PATCH 6/7] Update translation files Updated by "Update PO files to match POT (msgmerge)" hook in Weblate. Translation: storage-18.0/storage-18.0-fs_storage Translate-URL: https://translation.odoo-community.org/projects/storage-18-0/storage-18-0-fs_storage/ --- fs_storage/i18n/es.po | 16 ++++++++++++---- fs_storage/i18n/fr.po | 33 ++++++++++++++++++++++++--------- fs_storage/i18n/it.po | 19 +++++++++++++------ fs_storage/i18n/zh_CN.po | 15 +++++++++++---- 4 files changed, 60 insertions(+), 23 deletions(-) diff --git a/fs_storage/i18n/es.po b/fs_storage/i18n/es.po index d3b35511c8..b0451fa52b 100644 --- a/fs_storage/i18n/es.po +++ b/fs_storage/i18n/es.po @@ -26,6 +26,12 @@ msgstr "Opciones disponibles" msgid "Available properties" msgstr "Propiedades disponibles" +#. module: fs_storage +#. odoo-python +#: code:addons/fs_storage/models/fs_storage.py:0 +msgid "Calling fs.storage.%(reason)s is not allowed in a safe_eval context." +msgstr "" + #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__check_connection_method #: model:ir.model.fields,field_description:fs_storage.field_fs_test_connection__check_connection_method @@ -368,14 +374,16 @@ msgstr "" msgid "" "Technical code used to identify the storage backend into the code.This code " "must be unique. This code is used for example to define the storage backend " -"to store the attachments via the configuration parameter 'ir_attachment." -"storage.force.database' when the module 'fs_attachment' is installed." +"to store the attachments via the configuration parameter " +"'ir_attachment.storage.force.database' when the module 'fs_attachment' is " +"installed." msgstr "" "Código técnico utilizado para identificar el servidor de almacenamiento en " "el código. Este código debe ser único. Este código se utiliza, por ejemplo, " "para definir el servidor de almacenamiento para guardar los archivos " -"adjuntos mediante el parámetro de configuración \"ir_attachment.storage." -"force.database\" cuando se instala el módulo \"fs_attachment\"." +"adjuntos mediante el parámetro de configuración " +"\"ir_attachment.storage.force.database\" cuando se instala el módulo " +"\"fs_attachment\"." #. module: fs_storage #: model_terms:ir.ui.view,arch_db:fs_storage.fs_test_connection_form_view diff --git a/fs_storage/i18n/fr.po b/fs_storage/i18n/fr.po index e353d5b968..799fcaec06 100644 --- a/fs_storage/i18n/fr.po +++ b/fs_storage/i18n/fr.po @@ -26,6 +26,12 @@ msgstr "Options disponibles" msgid "Available properties" msgstr "Propriétés disponibles" +#. module: fs_storage +#. odoo-python +#: code:addons/fs_storage/models/fs_storage.py:0 +msgid "Calling fs.storage.%(reason)s is not allowed in a safe_eval context." +msgstr "" + #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__check_connection_method #: model:ir.model.fields,field_description:fs_storage.field_fs_test_connection__check_connection_method @@ -166,8 +172,11 @@ msgstr "" #: model:ir.model.fields,help:fs_storage.field_fs_storage__is_cacheable msgid "" "If True, once instantiated, the filesystem will be cached and reused.\n" -"By default, the filesystem is cacheable but in some cases, like when using OAuth2 authentication, the filesystem cannot be cached because it depends on the user and the token can change.\n" -"In this case, you can set this field to False to avoid caching the filesystem." +"By default, the filesystem is cacheable but in some cases, like when using " +"OAuth2 authentication, the filesystem cannot be cached because it depends on " +"the user and the token can change.\n" +"In this case, you can set this field to False to avoid caching the " +"filesystem." msgstr "" #. module: fs_storage @@ -346,7 +355,9 @@ msgstr "Serveur par défaut de l’environnement" #: model:ir.model.fields,help:fs_storage.field_fs_storage__check_connection_method #: model:ir.model.fields,help:fs_storage.field_fs_storage__x_check_connection_method_env_default msgid "" -"Set a method if you want the connection to remote to be checked every time the storage is used, in order to remove the obsolete connection from the cache.\n" +"Set a method if you want the connection to remote to be checked every time " +"the storage is used, in order to remove the obsolete connection from the " +"cache.\n" "* Create Marker file : Create a file on remote and check it exists\n" "* List File : List all files from root directory" msgstr "" @@ -376,9 +387,9 @@ msgid "" msgstr "" "Code technique utilisé pour identifier le stockage dans le code. Le code " "doit être unique. Le code est entre autre utilisé pour définir le stockage à " -"utiliser pour stocker les pièces jointes via le paramètre de configuration «" -" ir_attachment.storage.force.database » lorsque le module fs_attachhment est " -"installé." +"utiliser pour stocker les pièces jointes via le paramètre de configuration " +"« ir_attachment.storage.force.database » lorsque le module fs_attachhment " +"est installé." #. module: fs_storage #: model_terms:ir.ui.view,arch_db:fs_storage.fs_test_connection_form_view @@ -423,7 +434,8 @@ msgid "" " }\n" "}\n" "For more information, please refer to the fsspec documentation:\n" -"https://filesystem-spec.readthedocs.io/en/latest/api.html#built-in-implementations" +"https://filesystem-spec.readthedocs.io/en/latest/api.html#built-in-" +"implementations" msgstr "" "Les options pour initialiser le système de fichier.\n" "C’est un champ JSON qui dépend du protocole utilisé.\n" @@ -447,8 +459,11 @@ msgstr "" #: model:ir.model.fields,help:fs_storage.field_fs_storage__x_protocol_env_default msgid "" "The protocol used to access the content of filesystem.\n" -"This list is the one supported by the fsspec library (see https://filesystem-spec.readthedocs.io/en/latest). A filesystem protocolis added by default and refers to the odoo local filesystem.\n" -"Pay attention that according to the protocol, some options must beprovided through the options field." +"This list is the one supported by the fsspec library (see https://filesystem-" +"spec.readthedocs.io/en/latest). A filesystem protocolis added by default and " +"refers to the odoo local filesystem.\n" +"Pay attention that according to the protocol, some options must beprovided " +"through the options field." msgstr "" "Le protocole utilisé pour accéder le contenu du système de fichier.\n" "Cette liste contient ce qui est supporté par la bibliothèque fsspec (voir " diff --git a/fs_storage/i18n/it.po b/fs_storage/i18n/it.po index 73a5400222..3d999d835b 100644 --- a/fs_storage/i18n/it.po +++ b/fs_storage/i18n/it.po @@ -26,6 +26,12 @@ msgstr "Opzioni disponibili" msgid "Available properties" msgstr "Proprietà disponibili" +#. module: fs_storage +#. odoo-python +#: code:addons/fs_storage/models/fs_storage.py:0 +msgid "Calling fs.storage.%(reason)s is not allowed in a safe_eval context." +msgstr "" + #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__check_connection_method #: model:ir.model.fields,field_description:fs_storage.field_fs_test_connection__check_connection_method @@ -140,8 +146,8 @@ msgstr "Campo" msgid "" "Field %(field)s already stored in another FS storage ('%(other_storage)s')" msgstr "" -"Il campo %(field)s è già archiviato in un altro deposito FS " -"('%(other_storage)s')" +"Il campo %(field)s è già archiviato in un altro deposito FS ('%" +"(other_storage)s')" #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__field_xmlids @@ -286,8 +292,8 @@ msgstr "Modello" msgid "" "Model %(model)s already stored in another FS storage ('%(other_storage)s')" msgstr "" -"Il modello %(model)s è già archiviato in un altro deposito FS " -"('%(other_storage)s')" +"Il modello %(model)s è già archiviato in un altro deposito FS ('%" +"(other_storage)s')" #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__model_xmlids @@ -400,8 +406,9 @@ msgstr "Deposito" msgid "" "Technical code used to identify the storage backend into the code.This code " "must be unique. This code is used for example to define the storage backend " -"to store the attachments via the configuration parameter 'ir_attachment." -"storage.force.database' when the module 'fs_attachment' is installed." +"to store the attachments via the configuration parameter " +"'ir_attachment.storage.force.database' when the module 'fs_attachment' is " +"installed." msgstr "" "Codice tecnico usato per identificare il backend deposito nel codice. Questo " "codice deve essere univoco. Questo codice è utilizzato per esempio per " diff --git a/fs_storage/i18n/zh_CN.po b/fs_storage/i18n/zh_CN.po index 83909c7966..8271d52cd8 100644 --- a/fs_storage/i18n/zh_CN.po +++ b/fs_storage/i18n/zh_CN.po @@ -26,6 +26,12 @@ msgstr "可用选项" msgid "Available properties" msgstr "可用属性" +#. module: fs_storage +#. odoo-python +#: code:addons/fs_storage/models/fs_storage.py:0 +msgid "Calling fs.storage.%(reason)s is not allowed in a safe_eval context." +msgstr "" + #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__check_connection_method #: model:ir.model.fields,field_description:fs_storage.field_fs_test_connection__check_connection_method @@ -367,12 +373,13 @@ msgstr "" msgid "" "Technical code used to identify the storage backend into the code.This code " "must be unique. This code is used for example to define the storage backend " -"to store the attachments via the configuration parameter 'ir_attachment." -"storage.force.database' when the module 'fs_attachment' is installed." +"to store the attachments via the configuration parameter " +"'ir_attachment.storage.force.database' when the module 'fs_attachment' is " +"installed." msgstr "" "用于在代码中标识存储后端的技术代码。此代码必须是唯一的。例如,当安" -"装'fs_attachment'模块时,此代码用于通过配置参数'ir_attachment.storage.force." -"database'定义存储附件的存储后端。" +"装'fs_attachment'模块时,此代码用于通过配置参" +"数'ir_attachment.storage.force.database'定义存储附件的存储后端。" #. module: fs_storage #: model_terms:ir.ui.view,arch_db:fs_storage.fs_test_connection_form_view From 89130b75f85291597766b2b0b212297613760330 Mon Sep 17 00:00:00 2001 From: mymage Date: Mon, 23 Mar 2026 08:10:52 +0000 Subject: [PATCH 7/7] Translated using Weblate (Italian) Currently translated at 100.0% (72 of 72 strings) Translation: storage-18.0/storage-18.0-fs_storage Translate-URL: https://translation.odoo-community.org/projects/storage-18-0/storage-18-0-fs_storage/it/ --- fs_storage/i18n/it.po | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fs_storage/i18n/it.po b/fs_storage/i18n/it.po index 3d999d835b..9b78eb9a98 100644 --- a/fs_storage/i18n/it.po +++ b/fs_storage/i18n/it.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 16.0\n" "Report-Msgid-Bugs-To: \n" -"PO-Revision-Date: 2025-10-21 08:43+0000\n" +"PO-Revision-Date: 2026-03-23 10:45+0000\n" "Last-Translator: mymage \n" "Language-Team: none\n" "Language: it\n" @@ -14,7 +14,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 5.10.4\n" +"X-Generator: Weblate 5.15.2\n" #. module: fs_storage #: model_terms:ir.ui.view,arch_db:fs_storage.fs_storage_form_view @@ -31,6 +31,8 @@ msgstr "Proprietà disponibili" #: code:addons/fs_storage/models/fs_storage.py:0 msgid "Calling fs.storage.%(reason)s is not allowed in a safe_eval context." msgstr "" +"La chiamata a fs.storage.%(reason)s non è consentita in un contesto " +"safe_eval." #. module: fs_storage #: model:ir.model.fields,field_description:fs_storage.field_fs_storage__check_connection_method