* * * * *\n"
+"┬ ┬ ┬ ┬ ┬\n"
+"│ │ │ │ │\n"
+"│ │ │ │ └ jour de la semaine (0 - 6) (0 est dimanche)\n"
+"│ │ │ └───── mois (1 - 12)\n"
+"│ │ └────────── jour du mois (1 - 31)\n"
+"│ └──────────────── heure (0 - 23)\n"
+"└──────────────────── minute (0 - 59)\n\n"
+"---\n\n"
+"* - Toute valeur\n"
+"/ - Valeurs d'étape\n"
+"
\n"
#. Content of the 'Example' (HTML) field in DocType 'Workflow Transition'
#: frappe/workflow/doctype/workflow_transition/workflow_transition.json
@@ -1153,7 +1164,7 @@ msgstr ""
#: frappe/public/js/frappe/form/grid.js:66
msgid "Add Multiple"
-msgstr ""
+msgstr "Ajout multiple"
#: frappe/core/page/permission_manager/permission_manager.js:445
msgid "Add New Permission Rule"
@@ -1656,7 +1667,7 @@ msgstr "Tous les champs sont nécessaires pour soumettre le commentaire."
#. Description of the 'Document States' (Table) field in DocType 'Workflow'
#: frappe/workflow/doctype/workflow/workflow.json
msgid "All possible Workflow States and roles of the workflow. Docstatus Options: 0 is \"Saved\", 1 is \"Submitted\" and 2 is \"Cancelled\""
-msgstr "Tous les états de flux de travail et les rôles possibles du flux de travail. Les options d'état de Doc: 0 sont \"Enregistrés\", 1 est \"Envoyé\" et 2 est \"Annulé\""
+msgstr "Tous les états de workflow et les rôles possibles du workflow. Les options d'état de Doc: 0 sont \"Enregistrés\", 1 est \"Envoyé\" et 2 est \"Annulé\""
#: frappe/utils/password_strength.py:183
msgid "All-uppercase is almost as easy to guess as all-lowercase."
@@ -1696,7 +1707,7 @@ msgstr "Autoriser la Modification en Masse"
#. Label of the allow_edit (Check) field in DocType 'List View Settings'
#: frappe/desk/doctype/list_view_settings/list_view_settings.json
msgid "Allow Bulk Editing"
-msgstr ""
+msgstr "Autoriser l'édition en masse"
#. Label of the allow_consecutive_login_attempts (Int) field in DocType 'System
#. Settings'
@@ -1854,7 +1865,8 @@ msgstr ""
#: frappe/desk/doctype/list_view_settings/list_view_settings.json
msgid "Allow editing even if the doctype has a workflow set up.\n\n"
"Does nothing if a workflow isn't set up."
-msgstr ""
+msgstr "Autoriser l'édition même s'il existe workflow configuré.\n\n"
+"Ne fais rien si un flux de travail n'est pas configuré."
#. Label of the allow_events_in_timeline (Check) field in DocType 'DocType'
#: frappe/core/doctype/doctype/doctype.json
@@ -1953,13 +1965,13 @@ msgstr "Autorisé dans les mentions"
#. Type'
#: frappe/core/doctype/user_type/user_type.json
msgid "Allowed Modules"
-msgstr ""
+msgstr "Modules autorisés"
#. Label of the allowed_roles (Table MultiSelect) field in DocType 'OAuth
#. Client'
#: frappe/integrations/doctype/oauth_client/oauth_client.json
msgid "Allowed Roles"
-msgstr ""
+msgstr "Rôles Autorisés"
#. Label of the allowed_embedding_domains (Small Text) field in DocType 'Web
#. Form'
@@ -2097,7 +2109,7 @@ msgstr "Ancêtres de"
#. Settings'
#: frappe/core/doctype/navbar_settings/navbar_settings.json
msgid "Announcement Widget"
-msgstr ""
+msgstr "Widget d'annonce"
#. Label of the announcements_section (Section Break) field in DocType 'Navbar
#. Settings'
@@ -2414,11 +2426,11 @@ msgstr "Voulez-vous vraiment réinitialiser toutes les personnalisations?"
#: frappe/workflow/doctype/workflow/workflow.js:125
msgid "Are you sure you want to save this document?"
-msgstr ""
+msgstr "Êtes-vous sûr de vouloir enregistrer ce document ?"
#: frappe/email/doctype/newsletter/newsletter.js:60
msgid "Are you sure you want to send this newsletter now?"
-msgstr ""
+msgstr "Etes-vous sûr de vouloir envoyer cette newsletter maintenant ?"
#: frappe/core/doctype/document_naming_rule/document_naming_rule.js:16
#: frappe/core/doctype/user_permission/user_permission_list.js:165
@@ -2463,7 +2475,7 @@ msgstr "Attribuer À"
#: frappe/public/js/frappe/form/sidebar/assign_to.js:181
msgid "Assign To User Group"
-msgstr ""
+msgstr "Affecter au groupe d'utilisateurs"
#. Label of the assign_to_users_section (Section Break) field in DocType
#. 'Assignment Rule'
@@ -2473,7 +2485,7 @@ msgstr "Attribuer aux utilisateurs"
#: frappe/public/js/frappe/form/sidebar/assign_to.js:260
msgid "Assign a user"
-msgstr ""
+msgstr "Affecter un utilisateur"
#: frappe/automation/doctype/assignment_rule/assignment_rule.js:52
msgid "Assign one by one, in sequence"
@@ -2521,7 +2533,7 @@ msgstr "Assigné À /Responsable"
#: frappe/public/js/frappe/form/sidebar/assign_to.js:269
msgid "Assigning..."
-msgstr ""
+msgstr "Affectation en cours..."
#. Option for the 'Type' (Select) field in DocType 'Notification Log'
#: frappe/desk/doctype/notification_log/notification_log.json
@@ -2561,7 +2573,7 @@ msgstr "Affectation de règle utilisateur"
#: frappe/automation/doctype/assignment_rule/assignment_rule.py:55
msgid "Assignment Rule is not allowed on document type {0}"
-msgstr ""
+msgstr "La règle d'affectation n'est pas autorisée sur le type de document {0}"
#. Label of the assignment_rules_section (Section Break) field in DocType
#. 'Assignment Rule'
@@ -2642,7 +2654,7 @@ msgstr "Joindre l'Impression"
#: frappe/public/js/frappe/file_uploader/WebLink.vue:10
msgid "Attach a web link"
-msgstr ""
+msgstr "Joindre un lien Web"
#: frappe/website/doctype/website_slideshow/website_slideshow.js:8
msgid "Attach files / urls and add in table."
@@ -2838,11 +2850,11 @@ msgstr "Autorisé"
#: frappe/www/attribution.html:20
msgid "Authors"
-msgstr ""
+msgstr "Auteurs"
#: frappe/www/attribution.html:37
msgid "Authors / Maintainers"
-msgstr ""
+msgstr "Auteurs / Mainteneurs"
#. Option for the 'Skip Authorization' (Select) field in DocType 'OAuth
#. Provider Settings'
@@ -2875,7 +2887,7 @@ msgstr "Répétition automatique"
#. Name of a DocType
#: frappe/automation/doctype/auto_repeat_day/auto_repeat_day.json
msgid "Auto Repeat Day"
-msgstr ""
+msgstr "Jour de répétition automatique"
#: frappe/automation/doctype/auto_repeat/auto_repeat.py:165
msgid "Auto Repeat Day{0} {1} has been repeated."
@@ -2887,7 +2899,7 @@ msgstr "La répétition automatique de la création de document a échoué"
#: frappe/automation/doctype/auto_repeat/auto_repeat.js:117
msgid "Auto Repeat Schedule"
-msgstr ""
+msgstr "Planification de répétition automatique"
#: frappe/public/js/frappe/utils/common.js:434
msgid "Auto Repeat created for this document"
@@ -2915,12 +2927,12 @@ msgstr "L'affectation automatique a échoué: {0}"
#. Label of the follow_assigned_documents (Check) field in DocType 'User'
#: frappe/core/doctype/user/user.json
msgid "Auto follow documents that are assigned to you"
-msgstr ""
+msgstr "Suivez automatiquement les documents qui vous sont affectés"
#. Label of the follow_shared_documents (Check) field in DocType 'User'
#: frappe/core/doctype/user/user.json
msgid "Auto follow documents that are shared with you"
-msgstr ""
+msgstr "Suivez automatiquement les documents partagés avec vous"
#. Label of the follow_liked_documents (Check) field in DocType 'User'
#: frappe/core/doctype/user/user.json
@@ -2939,7 +2951,7 @@ msgstr "Suivi automatique des documents que vous créez"
#: frappe/automation/doctype/auto_repeat/auto_repeat.py:227
msgid "Auto repeat failed. Please enable auto repeat after fixing the issues."
-msgstr ""
+msgstr "La répétition automatique a échoué. Veuillez activer la répétition automatique après avoir résolu les problèmes."
#. Option for the 'Type' (Select) field in DocType 'DocField'
#. Option for the 'Field Type' (Select) field in DocType 'Custom Field'
@@ -2953,7 +2965,7 @@ msgstr "Auto-complétion"
#. Option for the 'Naming Rule' (Select) field in DocType 'DocType'
#: frappe/core/doctype/doctype/doctype.json
msgid "Autoincrement"
-msgstr ""
+msgstr "Auto-incrémentation"
#. Description of a Card Break in the Build Workspace
#: frappe/core/workspace/build/build.json
@@ -2970,7 +2982,7 @@ msgstr "Message automatique"
#: frappe/core/doctype/user/user.json
#: frappe/public/js/frappe/ui/theme_switcher.js:69
msgid "Automatic"
-msgstr ""
+msgstr "Automatique"
#: frappe/email/doctype/email_account/email_account.py:776
msgid "Automatic Linking can be activated only for one Email Account."
@@ -2983,11 +2995,11 @@ msgstr "La liaison automatique ne peut être activée que si l'option Entran
#. Description of a DocType
#: frappe/automation/doctype/assignment_rule/assignment_rule.json
msgid "Automatically Assign Documents to Users"
-msgstr ""
+msgstr "Affecter automatiquement des documents aux utilisateurs"
#: frappe/public/js/frappe/list/list_view.js:128
msgid "Automatically applied a filter for recent data. You can disable this behavior from the list view settings."
-msgstr ""
+msgstr "Application automatique d'un filtre pour les données récentes. Vous pouvez désactiver ce comportement dans les paramètres de l'affichage de la liste."
#. Label of the auto_account_deletion (Int) field in DocType 'Website Settings'
#: frappe/website/doctype/website_settings/website_settings.json
@@ -3046,7 +3058,7 @@ msgstr "En attente Mot de Passe"
#: frappe/public/js/frappe/widgets/onboarding_widget.js:195
msgid "Awesome Work"
-msgstr ""
+msgstr "Excellent travail"
#: frappe/public/js/frappe/widgets/onboarding_widget.js:353
msgid "Awesome, now try making an entry yourself"
@@ -3168,16 +3180,16 @@ msgstr "Travaux en Arrière-plan"
#. Report'
#: frappe/desk/doctype/system_health_report/system_health_report.json
msgid "Background Jobs Check"
-msgstr ""
+msgstr "Vérification des Travaux en Arrière-plan"
#. Label of the background_jobs_queue (Autocomplete) field in DocType 'Webhook'
#: frappe/integrations/doctype/webhook/webhook.json
msgid "Background Jobs Queue"
-msgstr ""
+msgstr "Fille d'attente des Travaux en Arrière-plan"
#: frappe/public/js/frappe/list/bulk_operations.js:87
msgid "Background Print (required for >25 documents)"
-msgstr ""
+msgstr "Impression en tache d'arrière-plan (obligatoire pour > 25 documents)"
#. Label of the background_workers (Section Break) field in DocType 'System
#. Settings'
@@ -3190,7 +3202,7 @@ msgstr "Exécution d'Opérations en Arrière-Plan"
#: frappe/integrations/doctype/google_drive/google_drive.py:170
msgid "Backing up Data."
-msgstr ""
+msgstr "Sauvegarde des données."
#: frappe/integrations/doctype/google_drive/google_drive.js:32
msgid "Backing up to Google Drive."
@@ -3236,7 +3248,7 @@ msgstr "Fréquence de Sauvegarde"
#. Label of the backup_path (Data) field in DocType 'S3 Backup Settings'
#: frappe/integrations/doctype/s3_backup_settings/s3_backup_settings.json
msgid "Backup Path"
-msgstr ""
+msgstr "Chemin de sauvegarde"
#: frappe/desk/page/backups/backups.py:98
msgid "Backup job is already queued. You will receive an email with the download link"
@@ -3259,11 +3271,11 @@ msgstr "Sauvegardes"
#. Label of the backups_size (Float) field in DocType 'System Health Report'
#: frappe/desk/doctype/system_health_report/system_health_report.json
msgid "Backups (MB)"
-msgstr ""
+msgstr "Sauvegardes (MB)"
#: frappe/core/doctype/scheduled_job_type/scheduled_job_type.py:65
msgid "Bad Cron Expression"
-msgstr ""
+msgstr "Expression cron incorrecte"
#. Option for the 'Rounding Method' (Select) field in DocType 'System Settings'
#: frappe/core/doctype/system_settings/system_settings.json
@@ -3300,7 +3312,7 @@ msgstr "La Bannière est au-dessus de la Barre de Menu Supérieure."
#. Option for the 'Type' (Select) field in DocType 'Dashboard Chart'
#: frappe/desk/doctype/dashboard_chart/dashboard_chart.json
msgid "Bar"
-msgstr ""
+msgstr "Bar"
#. Option for the 'Type' (Select) field in DocType 'DocField'
#. Option for the 'Field Type' (Select) field in DocType 'Custom Field'
@@ -3539,7 +3551,7 @@ msgstr "Blogueur"
#: frappe/core/doctype/doctype_state/doctype_state.json
#: frappe/desk/doctype/kanban_board_column/kanban_board_column.json
msgid "Blue"
-msgstr ""
+msgstr "Bleue"
#. Label of the bold (Check) field in DocType 'DocField'
#. Label of the bold (Check) field in DocType 'Custom Field'
@@ -3962,7 +3974,7 @@ msgstr "Caméra"
#: frappe/website/doctype/web_page_view/web_page_view.json
#: frappe/website/report/website_analytics/website_analytics.js:39
msgid "Campaign"
-msgstr ""
+msgstr "Campagne"
#. Label of the campaign_description (Small Text) field in DocType 'UTM
#. Campaign'
@@ -5873,7 +5885,7 @@ msgstr ""
#: frappe/core/doctype/scheduled_job_type/scheduled_job_type.json
#: frappe/core/doctype/server_script/server_script.json
msgid "Cron"
-msgstr ""
+msgstr "Cron"
#. Label of the cron_format (Data) field in DocType 'Scheduled Job Type'
#. Label of the cron_format (Data) field in DocType 'Server Script'
@@ -5884,7 +5896,7 @@ msgstr "Format Cron"
#: frappe/core/doctype/scheduled_job_type/scheduled_job_type.py:59
msgid "Cron format is required for job types with Cron frequency."
-msgstr ""
+msgstr "Le format Cron est requis pour les types de tâches avec fréquence Cron."
#: frappe/public/js/frappe/file_uploader/ImageCropper.vue:34
msgid "Crop"
@@ -7101,7 +7113,7 @@ msgstr ""
#: frappe/website/doctype/website_slideshow_item/website_slideshow_item.json
#: frappe/www/attribution.html:24
msgid "Description"
-msgstr ""
+msgstr "Description"
#. Description of the 'Blog Intro' (Small Text) field in DocType 'Blog Post'
#: frappe/website/doctype/blog_post/blog_post.json
@@ -7167,7 +7179,7 @@ msgstr ""
#: frappe/workflow/doctype/workflow_action/workflow_action.json
#: frappe/workflow/doctype/workflow_state/workflow_state.json
msgid "Desk User"
-msgstr ""
+msgstr "Utilisateur du backoffice"
#. Name of a DocType
#: frappe/desk/doctype/desktop_icon/desktop_icon.json
@@ -7236,7 +7248,7 @@ msgstr "Désactiver l'actualisation automatique"
#. 'List View Settings'
#: frappe/desk/doctype/list_view_settings/list_view_settings.json
msgid "Disable Automatic Recency Filters"
-msgstr ""
+msgstr "Désactiver les filtres automatiques de récurrence"
#. Label of the disable_change_log_notification (Check) field in DocType
#. 'System Settings'
@@ -7248,7 +7260,7 @@ msgstr ""
#. Settings'
#: frappe/desk/doctype/list_view_settings/list_view_settings.json
msgid "Disable Comment Count"
-msgstr ""
+msgstr "Désactiver le comptage des commentaires"
#. Label of the disable_comments (Check) field in DocType 'Blog Post'
#: frappe/website/doctype/blog_post/blog_post.json
@@ -7619,7 +7631,7 @@ msgstr ""
#. Description of the 'Document Type' (Link) field in DocType 'Workflow'
#: frappe/workflow/doctype/workflow/workflow.json
msgid "DocType on which this Workflow is applicable."
-msgstr "DocType pour lequel ce Flux de Travail est applicable."
+msgstr "DocType pour lequel ce Workflow est applicable."
#: frappe/public/js/frappe/views/kanban/kanban_settings.js:4
msgid "DocType required"
@@ -8560,7 +8572,7 @@ msgstr ""
#: frappe/website/doctype/personal_data_deletion_request/personal_data_deletion_request.json
#: frappe/www/login.html:8 frappe/www/login.py:104
msgid "Email"
-msgstr ""
+msgstr "Courriel"
#. Label of a Link in the Tools Workspace
#. Label of the email_account (Link) field in DocType 'Communication'
@@ -12214,7 +12226,7 @@ msgstr "Si \"Appliquer des autorisations d'utilisateur strictes\" est coché et
#: frappe/workflow/doctype/workflow/workflow.json
#: frappe/workflow/doctype/workflow_document_state/workflow_document_state.json
msgid "If Checked workflow status will not override status in list view"
-msgstr "Si Cochée le statut du flux de travail ne remplacera pas le statut de la vue en liste"
+msgstr "Si coché, le statut du workflow ne remplacera pas le statut de la vue en liste"
#: frappe/core/doctype/doctype/doctype.py:1762
#: frappe/core/report/user_doctype_permissions/user_doctype_permissions.py:45
@@ -17029,7 +17041,7 @@ msgstr "Pas de courrier {0}"
#: frappe/public/js/frappe/form/grid_row.js:256
msgctxt "Title of the 'row number' column"
msgid "No."
-msgstr ""
+msgstr "N°."
#. Option for the 'Provider' (Select) field in DocType 'Geolocation Settings'
#: frappe/integrations/doctype/geolocation_settings/geolocation_settings.json
@@ -17057,7 +17069,7 @@ msgstr "Aucun"
#: frappe/public/js/frappe/form/workflow.js:36
msgid "None: End of Workflow"
-msgstr "Aucun: Fin de Flux de Travail"
+msgstr "Rien: Fin du Workflow"
#. Label of the normalized_copies (Int) field in DocType 'Recorder Query'
#: frappe/core/doctype/recorder_query/recorder_query.json
@@ -17176,7 +17188,7 @@ msgstr "Image utilisateur non valide."
#: frappe/model/workflow.py:114
msgid "Not a valid Workflow Action"
-msgstr "Action de flux de travail non valide"
+msgstr "Action de Workflow non valide"
#: frappe/templates/includes/login/login.js:255
msgid "Not a valid user"
@@ -17242,7 +17254,7 @@ msgstr "Non autorisé à afficher {0}"
#: frappe/automation/workspace/tools/tools.json
#: frappe/desk/doctype/note/note.json
msgid "Note"
-msgstr ""
+msgstr "Note"
#. Name of a DocType
#: frappe/desk/doctype/note_seen_by/note_seen_by.json
@@ -17665,7 +17677,7 @@ msgstr ""
#. Request'
#: frappe/website/doctype/personal_data_deletion_request/personal_data_deletion_request.json
msgid "On Hold"
-msgstr ""
+msgstr "En attente"
#. Option for the 'DocType Event' (Select) field in DocType 'Server Script'
#: frappe/core/doctype/server_script/server_script.json
@@ -18168,7 +18180,7 @@ msgstr "Sortie"
#: frappe/public/js/frappe/form/templates/form_dashboard.html:5
msgid "Overview"
-msgstr ""
+msgstr "Vue d'ensemble"
#: frappe/core/report/transaction_log_report/transaction_log_report.py:100
msgid "Owner"
@@ -21333,7 +21345,7 @@ msgstr "Type de Rapport"
#: frappe/public/js/frappe/list/base_list.js:203
msgid "Report View"
-msgstr ""
+msgstr "Vue rapport"
#: frappe/public/js/frappe/form/templates/form_sidebar.html:26
msgid "Report bug"
@@ -22072,7 +22084,7 @@ msgstr ""
#. Description of the 'Transitions' (Table) field in DocType 'Workflow'
#: frappe/workflow/doctype/workflow/workflow.json
msgid "Rules defining transition of state in the workflow."
-msgstr "Règles définissant la transition d'état dans le flux de travail"
+msgstr "Règles définissant la transition d'état dans le Workflow."
#. Description of the 'Transition Rules' (Section Break) field in DocType
#. 'Workflow'
@@ -25025,7 +25037,7 @@ msgstr ""
#: frappe/automation/doctype/auto_repeat/auto_repeat.json
#: frappe/automation/doctype/auto_repeat/auto_repeat.py:128
msgid "Submit on Creation"
-msgstr ""
+msgstr "Valider à la création"
#: frappe/public/js/frappe/widgets/onboarding_widget.js:395
msgid "Submit this document to complete this step."
@@ -29238,25 +29250,25 @@ msgstr ""
#: frappe/public/js/workflow_builder/store.js:129
#: frappe/workflow/doctype/workflow/workflow.json
msgid "Workflow"
-msgstr "Flux de Travail"
+msgstr "Workflow"
#. Name of a DocType
#: frappe/workflow/doctype/workflow_action/workflow_action.json
#: frappe/workflow/doctype/workflow_action/workflow_action.py:444
msgid "Workflow Action"
-msgstr "Action du Flux de Travail"
+msgstr "Action du Workflow"
#. Name of a DocType
#. Description of a DocType
#: frappe/workflow/doctype/workflow_action_master/workflow_action_master.json
msgid "Workflow Action Master"
-msgstr "Actions de Base du Flux de Travail"
+msgstr "Actions de Base du Workflow"
#. Label of the workflow_action_name (Data) field in DocType 'Workflow Action
#. Master'
#: frappe/workflow/doctype/workflow_action_master/workflow_action_master.json
msgid "Workflow Action Name"
-msgstr "Nom de l'Action du Flux de Travail"
+msgstr "Nom de l'Action du Workflow"
#. Name of a DocType
#: frappe/workflow/doctype/workflow_action_permitted_role/workflow_action_permitted_role.json
@@ -29267,13 +29279,13 @@ msgstr ""
#. Document State'
#: frappe/workflow/doctype/workflow_document_state/workflow_document_state.json
msgid "Workflow Action is not created for optional states"
-msgstr "L'action de flux de travail n'est pas créée pour les états facultatifs"
+msgstr "L’action du workflow n’est pas créée pour les états facultatifs"
#: frappe/public/js/workflow_builder/store.js:129
#: frappe/workflow/doctype/workflow/workflow.js:25
#: frappe/workflow/page/workflow_builder/workflow_builder.js:4
msgid "Workflow Builder"
-msgstr ""
+msgstr "Constructeur de Workflow"
#. Label of the workflow_builder_id (Data) field in DocType 'Workflow Document
#. State'
@@ -29300,24 +29312,24 @@ msgstr ""
#. Name of a DocType
#: frappe/workflow/doctype/workflow_document_state/workflow_document_state.json
msgid "Workflow Document State"
-msgstr "État du Document du Flux de Travail"
+msgstr "État du Document du Workflow"
#. Label of the workflow_name (Data) field in DocType 'Workflow'
#: frappe/workflow/doctype/workflow/workflow.json
msgid "Workflow Name"
-msgstr "Nom du Flux de Travail"
+msgstr "Nom du Workflow"
#. Label of the workflow_state (Data) field in DocType 'Workflow Action'
#. Name of a DocType
#: frappe/workflow/doctype/workflow_action/workflow_action.json
#: frappe/workflow/doctype/workflow_state/workflow_state.json
msgid "Workflow State"
-msgstr "État du Flux de Travail"
+msgstr "État du Workflow"
#. Label of the workflow_state_field (Data) field in DocType 'Workflow'
#: frappe/workflow/doctype/workflow/workflow.json
msgid "Workflow State Field"
-msgstr "Champ de l'État du Flux de Travail"
+msgstr "Champ de l'État du Workflow"
#: frappe/model/workflow.py:61
msgid "Workflow State not set"
@@ -29325,7 +29337,7 @@ msgstr "L'état du workflow n'est pas défini"
#: frappe/model/workflow.py:204 frappe/model/workflow.py:212
msgid "Workflow State transition not allowed from {0} to {1}"
-msgstr "La transition d'état du flux de travail n'est pas autorisée de {0} à {1}."
+msgstr "La transition d'état du workflow n'est pas autorisée de {0} à {1}"
#: frappe/workflow/doctype/workflow/workflow.js:140
msgid "Workflow States Don't Exist"
@@ -29338,7 +29350,7 @@ msgstr "Statut du workflow"
#. Name of a DocType
#: frappe/workflow/doctype/workflow_transition/workflow_transition.json
msgid "Workflow Transition"
-msgstr "Transition du Flux de Travail"
+msgstr "Transition du Workflow"
#. Description of a DocType
#: frappe/workflow/doctype/workflow_state/workflow_state.json
@@ -30831,7 +30843,7 @@ msgstr "aaaa-mm-jj"
#: frappe/desk/doctype/event/event.js:87
msgid "{0}"
-msgstr ""
+msgstr "{0}"
#: frappe/public/js/frappe/ui/toolbar/search_utils.js:193
msgid "{0} ${skip_list ? \"\" : type}"
@@ -31171,7 +31183,7 @@ msgstr ""
#: frappe/core/doctype/scheduled_job_type/scheduled_job_type.py:64
msgid "{0} is not a valid Cron expression."
-msgstr ""
+msgstr "{0} n'est pas une expression Cron valide."
#: frappe/public/js/frappe/form/controls/dynamic_link.js:27
msgid "{0} is not a valid DocType for Dynamic Link"
diff --git a/frappe/locale/sr_CS.po b/frappe/locale/sr_CS.po
index 248ac74bde..2ec6f861f9 100644
--- a/frappe/locale/sr_CS.po
+++ b/frappe/locale/sr_CS.po
@@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: frappe\n"
"Report-Msgid-Bugs-To: developers@frappe.io\n"
"POT-Creation-Date: 2025-05-18 09:33+0000\n"
-"PO-Revision-Date: 2025-05-25 10:26\n"
+"PO-Revision-Date: 2025-06-03 11:42\n"
"Last-Translator: developers@frappe.io\n"
"Language-Team: Serbian (Latin)\n"
"MIME-Version: 1.0\n"
@@ -1325,7 +1325,7 @@ msgstr "Dodaj korisničku dozvolu"
#. Label of the add_video_conferencing (Check) field in DocType 'Event'
#: frappe/desk/doctype/event/event.json
msgid "Add Video Conferencing"
-msgstr "Dodaj video konferenciju"
+msgstr "Dodaj video-konferenciju"
#: frappe/public/js/frappe/ui/filters/filter_list.js:298
msgid "Add a Filter"
@@ -5922,7 +5922,7 @@ msgstr "Kreiraj svoj prvi {0}"
#: frappe/workflow/doctype/workflow/workflow.js:16
msgid "Create your workflow visually using the Workflow Builder."
-msgstr "Kreirajte Vaš radni tok vizuelno koristeći uređivač radnog toka."
+msgstr "Kreirajte Vaš radni tok vizualno koristeći uređivač radnog toka."
#. Option for the 'Comment Type' (Select) field in DocType 'Comment'
#: frappe/core/doctype/comment/comment.json
@@ -8584,7 +8584,7 @@ msgstr "Uredite Vaš odgovor"
#: frappe/workflow/doctype/workflow/workflow.js:18
msgid "Edit your workflow visually using the Workflow Builder."
-msgstr "Vizuelno uredite svoj radni tok pomoću uređivača radnog toka."
+msgstr "Vizualno uredite svoj radni tok pomoću uređivača radnog toka."
#: frappe/public/js/frappe/views/reports/report_view.js:672
#: frappe/public/js/frappe/widgets/widget_dialog.js:52
@@ -13209,7 +13209,7 @@ msgstr "Interna evidencija deljenja dokumenata"
#. Label of the intro_video_url (Data) field in DocType 'Onboarding Step'
#: frappe/desk/doctype/onboarding_step/onboarding_step.json
msgid "Intro Video URL"
-msgstr "URL uvodnog video snimka"
+msgstr "URL uvodnog video-snimka"
#. Description of the 'Company Introduction' (Text Editor) field in DocType
#. 'About Us Settings'
@@ -13859,7 +13859,7 @@ msgstr "Zadatak nije pokrenut."
#: frappe/desk/doctype/event/event.js:55
msgid "Join video conference with {0}"
-msgstr "Pridruži se video konferenciji sa {0}"
+msgstr "Pridruži se video-konferenciji sa {0}"
#: frappe/public/js/frappe/form/toolbar.js:395
#: frappe/public/js/frappe/form/toolbar.js:830
@@ -29431,7 +29431,7 @@ msgstr "ID uređivača radnog toka"
#: frappe/workflow/doctype/workflow/workflow.js:11
msgid "Workflow Builder allows you to create workflows visually. You can drag and drop states and link them to create transitions. Also you can update thieir properties from the sidebar."
-msgstr "Uređivač radnog toka Vam dozvoljava da vizuelno kreirate radne tokove. Možete prevlačiti i puštati stanja i povezivati ih kako biste napravili tranzicije. Takođe, možete ažurirati njihova svojstva putem bočne trake."
+msgstr "Uređivač radnog toka Vam dozvoljava da vizualno kreirate radne tokove. Možete prevlačiti i puštati stanja i povezivati ih kako biste napravili tranzicije. Takođe, možete ažurirati njihova svojstva putem bočne trake."
#. Label of the workflow_data (JSON) field in DocType 'Workflow'
#: frappe/workflow/doctype/workflow/workflow.json
diff --git a/frappe/locale/sv.po b/frappe/locale/sv.po
index 378bcbf981..aa13387bf3 100644
--- a/frappe/locale/sv.po
+++ b/frappe/locale/sv.po
@@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: frappe\n"
"Report-Msgid-Bugs-To: developers@frappe.io\n"
"POT-Creation-Date: 2025-05-18 09:33+0000\n"
-"PO-Revision-Date: 2025-05-26 10:24\n"
+"PO-Revision-Date: 2025-06-05 11:49\n"
"Last-Translator: developers@frappe.io\n"
"Language-Team: Swedish\n"
"MIME-Version: 1.0\n"
@@ -5178,7 +5178,7 @@ msgstr "Kommentarer"
#. Description of the 'Timeline Field' (Data) field in DocType 'DocType'
#: frappe/core/doctype/doctype/doctype.json
msgid "Comments and Communications will be associated with this linked document"
-msgstr "Kommentarer och E-post kommer att kopplas till detta länkade dokument"
+msgstr "Kommentarer och Kommunikation kommer att kopplas till detta länkade dokument"
#: frappe/templates/includes/comments/comments.py:38
msgid "Comments cannot have links or email addresses"
@@ -5213,22 +5213,22 @@ msgstr "Vanliga förnamn och efternamn är lätta att gissa."
#: frappe/email/doctype/email_queue/email_queue.json
#: frappe/tests/test_translate.py:35 frappe/tests/test_translate.py:119
msgid "Communication"
-msgstr "Konversation"
+msgstr "Kommunikation"
#. Name of a DocType
#: frappe/core/doctype/communication_link/communication_link.json
msgid "Communication Link"
-msgstr "Konversation Länk"
+msgstr "Kommunikation Länk"
#. Label of a Link in the Build Workspace
#: frappe/core/workspace/build/build.json
msgid "Communication Logs"
-msgstr "Konversation Logg"
+msgstr "Kommunikation Logg"
#. Label of the communication_type (Select) field in DocType 'Communication'
#: frappe/core/doctype/communication/communication.json
msgid "Communication Type"
-msgstr "Konversation Typ"
+msgstr "Kommunikation Typ"
#: frappe/integrations/frappe_providers/frappecloud_billing.py:32
msgid "Communication secret not set"
@@ -12115,7 +12115,7 @@ msgstr "Regel med högre prioritet tillämpas först"
#. Label of the highlight (Text) field in DocType 'Company History'
#: frappe/website/doctype/company_history/company_history.json
msgid "Highlight"
-msgstr "Markera"
+msgstr "Höjdpunkt"
#: frappe/www/update-password.html:276
msgid "Hint: Include symbols, numbers and capital letters in the password"
@@ -13170,7 +13170,7 @@ msgstr "Integration Begäran"
#: frappe/integrations/workspace/integrations/integrations.json
#: frappe/website/doctype/website_settings/website_settings.json
msgid "Integrations"
-msgstr "Integrationer"
+msgstr "System Integrationer"
#. Description of the 'Delivery Status' (Select) field in DocType
#. 'Communication'
@@ -30014,7 +30014,7 @@ msgstr "Du har inte lagt till några Översiktpanel Diagram eller Nummerkort än
#: frappe/public/js/frappe/list/list_view.js:498
msgid "You haven't created a {0} yet"
-msgstr "Du har inte skapat {0} än"
+msgstr "Ingen {0} skapad än"
#: frappe/rate_limiter.py:166
msgid "You hit the rate limit because of too many requests. Please try after sometime."
diff --git a/frappe/locale/tr.po b/frappe/locale/tr.po
index d9c6cb6d47..d335db9d96 100644
--- a/frappe/locale/tr.po
+++ b/frappe/locale/tr.po
@@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: frappe\n"
"Report-Msgid-Bugs-To: developers@frappe.io\n"
"POT-Creation-Date: 2025-05-18 09:33+0000\n"
-"PO-Revision-Date: 2025-05-19 07:02\n"
+"PO-Revision-Date: 2025-06-04 11:43\n"
"Last-Translator: developers@frappe.io\n"
"Language-Team: Turkish\n"
"MIME-Version: 1.0\n"
@@ -3330,7 +3330,7 @@ msgstr "Yedekleme Sıklığı"
#. Label of the backup_path (Data) field in DocType 'S3 Backup Settings'
#: frappe/integrations/doctype/s3_backup_settings/s3_backup_settings.json
msgid "Backup Path"
-msgstr ""
+msgstr "Yedekleme Yolu"
#: frappe/desk/page/backups/backups.py:98
msgid "Backup job is already queued. You will receive an email with the download link"
@@ -13912,7 +13912,7 @@ msgstr "Tüm güncelleme akışlarını takip edin"
#. Description of a DocType
#: frappe/core/doctype/communication/communication.json
msgid "Keeps track of all communications"
-msgstr ""
+msgstr "Tüm iletişimleri takip eder"
#. Label of the defkey (Data) field in DocType 'DefaultValue'
#. Label of the key (Data) field in DocType 'Document Share Key'
@@ -14217,11 +14217,11 @@ msgstr "Son 10 Aktif Kullanıcı"
#: frappe/public/js/frappe/ui/filters/filter.js:627
msgid "Last 14 Days"
-msgstr ""
+msgstr "Son 14 Gün"
#: frappe/public/js/frappe/ui/filters/filter.js:631
msgid "Last 30 Days"
-msgstr ""
+msgstr "Son 30 Gün"
#: frappe/public/js/frappe/ui/filters/filter.js:651
msgid "Last 6 Months"
@@ -14229,11 +14229,11 @@ msgstr ""
#: frappe/public/js/frappe/ui/filters/filter.js:623
msgid "Last 7 Days"
-msgstr ""
+msgstr "Son 7 Gün"
#: frappe/public/js/frappe/ui/filters/filter.js:635
msgid "Last 90 Days"
-msgstr ""
+msgstr "Son 90 Gün"
#. Label of the last_active (Datetime) field in DocType 'User'
#: frappe/core/doctype/user/user.json
diff --git a/frappe/model/base_document.py b/frappe/model/base_document.py
index 5ccfbf0cce..fac66fa4d8 100644
--- a/frappe/model/base_document.py
+++ b/frappe/model/base_document.py
@@ -474,9 +474,6 @@ class BaseDocument:
else:
value = get_not_null_defaults(df.fieldtype)
- if hasattr(value, "__value__"):
- value = value.__value__()
-
d[fieldname] = value
return d
@@ -847,6 +844,8 @@ class BaseDocument:
def get_invalid_links(self, is_submittable=False):
"""Return list of invalid links and also update fetch values if not set."""
+ is_submittable = is_submittable or self.meta.is_submittable
+
def get_msg(df, docname):
# check if parentfield exists (only applicable for child table doctype)
if self.get("parentfield"):
@@ -859,76 +858,81 @@ class BaseDocument:
for df in self.meta.get_link_fields() + self.meta.get("fields", {"fieldtype": ("=", "Dynamic Link")}):
docname = self.get(df.fieldname)
+ if not docname:
+ continue
- if docname:
- if df.fieldtype == "Link":
- doctype = df.options
- if not doctype:
- frappe.throw(_("Options not set for link field {0}").format(df.fieldname))
- else:
- doctype = self.get(df.options)
- if not doctype:
- frappe.throw(_("{0} must be set first").format(self.meta.get_label(df.options)))
- invalidate_distinct_link_doctypes(df.parent, df.options, doctype)
+ assert isinstance(docname, str | int) or (
+ isinstance(docname, list | tuple | set) and len(docname) == 1
+ ), f"Unexpected value for field {df.fieldname}: {docname}"
+ if df.fieldtype == "Link":
+ doctype = df.options
+ if not doctype:
+ frappe.throw(_("Options not set for link field {0}").format(df.fieldname))
+ else:
+ assert df.fieldtype == "Dynamic Link"
+ doctype = self.get(df.options)
+ if not doctype:
+ frappe.throw(_("{0} must be set first").format(self.meta.get_label(df.options)))
+ invalidate_distinct_link_doctypes(df.parent, df.options, doctype)
+
+ meta = frappe.get_meta(doctype)
+ if not meta.istable:
+ notify_link_count(doctype, docname)
+
+ check_docstatus = is_submittable and frappe.get_meta(doctype).is_submittable
+
+ # get a map of values ot fetch along with this link query
+ # that are mapped as link_fieldname.source_fieldname in Options of
+ # Readonly or Data or Text type fields
+ fields_to_fetch = [
+ _df
+ for _df in self.meta.get_fields_to_fetch(df.fieldname)
+ if not _df.get("fetch_if_empty")
+ or (_df.get("fetch_if_empty") and not self.get(_df.fieldname))
+ ]
+ values_to_fetch = (
+ "name",
+ *(_df.fetch_from.split(".")[-1] for _df in fields_to_fetch),
+ )
+ if check_docstatus:
+ values_to_fetch += ("docstatus",)
+
+ if not meta.get("is_virtual"):
+ values = frappe.db.get_value(
+ doctype, docname, values_to_fetch, as_dict=True, cache=True, order_by=None
+ )
+ if not values: # NOTE: DB Value cache does negative caching, which is hard to remove now.
+ values = frappe.db.get_value(
+ doctype, docname, values_to_fetch, as_dict=True, order_by=None
+ )
+ else:
+ values = frappe.get_doc(doctype, docname).as_dict()
+
+ # fallback to dict with field_to_fetch=None if link field value is not found
+ # (for compatibility, `values` must have same data type)
+ values = values or _dict.fromkeys(values_to_fetch, None)
+
+ if getattr(meta, "issingle", 0):
+ values.name = doctype
+
+ if not df.get("is_virtual"):
# MySQL is case insensitive. Preserve case of the original docname in the Link Field.
+ setattr(self, df.fieldname, values.name)
- # get a map of values ot fetch along with this link query
- # that are mapped as link_fieldname.source_fieldname in Options of
- # Readonly or Data or Text type fields
+ for _df in fields_to_fetch:
+ if self.is_new() or not self.docstatus.is_submitted() or _df.allow_on_submit:
+ self.set_fetch_from_value(doctype, _df, values)
- meta = frappe.get_meta(doctype)
- fields_to_fetch = [
- _df
- for _df in self.meta.get_fields_to_fetch(df.fieldname)
- if not _df.get("fetch_if_empty")
- or (_df.get("fetch_if_empty") and not self.get(_df.fieldname))
- ]
- if not meta.get("is_virtual"):
- if not fields_to_fetch:
- # cache a single value type
- values = _dict(name=frappe.db.get_value(doctype, docname, "name", cache=True))
- else:
- values_to_fetch = ["name"] + [
- _df.fetch_from.split(".")[-1] for _df in fields_to_fetch
- ]
+ if not values.name:
+ invalid_links.append((df.fieldname, docname, get_msg(df, docname)))
- # fallback to dict with field_to_fetch=None if link field value is not found
- # (for compatibility, `values` must have same data type)
- empty_values = _dict({value: None for value in values_to_fetch})
- # don't cache if fetching other values too
- values = (
- frappe.db.get_value(doctype, docname, values_to_fetch, as_dict=True)
- or empty_values
- )
-
- if getattr(meta, "issingle", 0):
- values.name = doctype
-
- if meta.get("is_virtual"):
- values = frappe.get_doc(doctype, docname).as_dict()
-
- if values:
- if not df.get("is_virtual"):
- setattr(self, df.fieldname, values.name)
-
- for _df in fields_to_fetch:
- if self.is_new() or not self.docstatus.is_submitted() or _df.allow_on_submit:
- self.set_fetch_from_value(doctype, _df, values)
-
- if not meta.istable:
- notify_link_count(doctype, docname)
-
- if not values.name:
- invalid_links.append((df.fieldname, docname, get_msg(df, docname)))
-
- elif (
- df.fieldname != "amended_from"
- and (is_submittable or self.meta.is_submittable)
- and frappe.get_meta(doctype).is_submittable
- and DocStatus(frappe.db.get_value(doctype, docname, "docstatus") or 0).is_cancelled()
- ):
- cancelled_links.append((df.fieldname, docname, get_msg(df, docname)))
+ elif (
+ df.fieldname != "amended_from"
+ and check_docstatus
+ and DocStatus(values.docstatus or 0).is_cancelled()
+ ):
+ cancelled_links.append((df.fieldname, docname, get_msg(df, docname)))
return invalid_links, cancelled_links
diff --git a/frappe/model/create_new.py b/frappe/model/create_new.py
index 84fc2e1e5b..973d9fb619 100644
--- a/frappe/model/create_new.py
+++ b/frappe/model/create_new.py
@@ -41,7 +41,7 @@ def make_new_doc(doctype):
doc["doctype"] = doctype
doc["__islocal"] = 1
- if not frappe.model.meta.is_single(doctype):
+ if not getattr(doc.meta, "issingle", False):
doc["__unsaved"] = 1
return doc
diff --git a/frappe/model/db_query.py b/frappe/model/db_query.py
index b34c9c5c20..27563323fa 100644
--- a/frappe/model/db_query.py
+++ b/frappe/model/db_query.py
@@ -116,6 +116,8 @@ class DatabaseQuery:
*,
parent_doctype=None,
) -> list:
+ self.user = user or frappe.session.user
+
if not ignore_permissions:
self.check_read_permission(self.doctype, parent_doctype=parent_doctype)
@@ -167,7 +169,6 @@ class DatabaseQuery:
self.as_list = as_list
self.ignore_ifnull = ignore_ifnull
self.flags.ignore_permissions = ignore_permissions
- self.user = user or frappe.session.user
self.update = update
self.user_settings_fields = copy.deepcopy(self.fields)
self.run = run
@@ -929,7 +930,7 @@ from {tables}
df
and (db_type := cstr(frappe.db.type_map.get(df.fieldtype, " ")[0]))
and db_type in ("varchar", "text", "longtext", "smalltext", "json")
- ):
+ ) or f.fieldname in ("owner", "modified_by", "parent", "parentfield", "parenttype"):
value = cstr(f.value)
fallback = "''"
diff --git a/frappe/model/document.py b/frappe/model/document.py
index e81524bc84..07dbef551a 100644
--- a/frappe/model/document.py
+++ b/frappe/model/document.py
@@ -24,7 +24,7 @@ from frappe.model.docstatus import DocStatus
from frappe.model.naming import set_new_name, validate_name
from frappe.model.utils import is_virtual_doctype, simple_singledispatch
from frappe.model.workflow import set_workflow_state_on_action, validate_workflow
-from frappe.types import DF, DocRef
+from frappe.types import DF
from frappe.utils import compare, cstr, date_diff, file_lock, flt, get_table_name, now
from frappe.utils.data import get_absolute_url, get_datetime, get_timedelta, getdate
from frappe.utils.global_search import update_global_search
@@ -105,7 +105,7 @@ def get_doc(*args, **kwargs) -> "Document":
if not args and kwargs:
return get_doc_from_dict(kwargs)
else:
- raise ValueError("First non keyword argument must be a string, dict or DocRef")
+ raise ValueError("First non keyword argument must be a string or dict")
@get_doc.register(BaseDocument)
@@ -113,11 +113,6 @@ def _basedoc(doc: BaseDocument, *args, **kwargs) -> "Document":
return doc
-@get_doc.register(DocRef)
-def _docref(doc_ref: DocRef, **kwargs) -> "Document":
- return get_doc(doc_ref.doctype, doc_ref.name, **kwargs)
-
-
@get_doc.register(str)
def get_doc_str(doctype: str, name: str | None = None, **kwargs) -> "Document":
# if no name: it's a single
@@ -143,7 +138,7 @@ def get_doc_from_dict(data: dict[str, Any], **kwargs) -> "Document":
raise ImportError(data["doctype"])
-class Document(BaseDocument, DocRef):
+class Document(BaseDocument):
"""All controllers inherit from `Document`."""
doctype: DF.Data
@@ -197,9 +192,6 @@ class Document(BaseDocument, DocRef):
if isinstance(arg, dict):
return self._init_from_kwargs(arg)
- if isinstance(arg, DocRef):
- return self._init_known_doc(arg.doctype, arg.name, **kwargs)
-
raise ValueError(f"Unsupported argument type: {type(arg)}")
@property
@@ -774,7 +766,7 @@ class Document(BaseDocument, DocRef):
)
if self.doctype in frappe.db.value_cache:
- del frappe.db.value_cache[self.doctype]
+ frappe.db.value_cache.pop(self.doctype, None)
def set_user_and_timestamp(self):
self._original_modified = self.modified
@@ -1464,7 +1456,7 @@ class Document(BaseDocument, DocRef):
self.set("modified_by", frappe.session.user)
# load but do not reload doc_before_save because before_change or on_change might expect it
- if not self.get_doc_before_save():
+ if not self.get_doc_before_save() and not self.meta.istable:
self.load_doc_before_save()
# to trigger notification on value change
diff --git a/frappe/model/meta.py b/frappe/model/meta.py
index 3943507999..c182a74e22 100644
--- a/frappe/model/meta.py
+++ b/frappe/model/meta.py
@@ -38,11 +38,11 @@ from frappe.model.base_document import (
BaseDocument,
)
from frappe.model.document import Document
+from frappe.model.utils import is_single_doctype
from frappe.model.workflow import get_workflow_name
from frappe.modules import load_doctype_module
-from frappe.types import DocRef
from frappe.utils import cached_property, cast, cint, cstr
-from frappe.utils.caching import request_cache
+from frappe.utils.caching import site_cache
from frappe.utils.data import add_to_date, get_datetime
DEFAULT_FIELD_LABELS = {
@@ -837,13 +837,6 @@ class Meta(Document):
#######
-def is_single(doctype):
- try:
- return frappe.db.get_value("DocType", doctype, "issingle")
- except IndexError:
- raise Exception("Cannot determine whether {} is single".format(doctype))
-
-
def get_parent_dt(dt):
if not frappe.is_table(dt):
return ""
@@ -1021,3 +1014,7 @@ if typing.TYPE_CHECKING:
class _Meta(Meta, DocType):
pass
+
+
+# backward compatibility
+is_single = is_single_doctype
diff --git a/frappe/model/naming.py b/frappe/model/naming.py
index ff64d10b0d..44fe56824c 100644
--- a/frappe/model/naming.py
+++ b/frappe/model/naming.py
@@ -538,9 +538,7 @@ def _set_amended_name(doc):
"Amended Document Naming Settings", {"document_type": doc.doctype}, "action", cache=True
)
if not amend_naming_rule:
- amend_naming_rule = frappe.db.get_single_value(
- "Document Naming Settings", "default_amend_naming", cache=True
- )
+ amend_naming_rule = frappe.get_single_value("Document Naming Settings", "default_amend_naming")
if amend_naming_rule == "Default Naming":
return
diff --git a/frappe/printing/doctype/letter_head/test_letter_head.py b/frappe/printing/doctype/letter_head/test_letter_head.py
index fe1b5da023..8273515fc7 100644
--- a/frappe/printing/doctype/letter_head/test_letter_head.py
+++ b/frappe/printing/doctype/letter_head/test_letter_head.py
@@ -1,16 +1,7 @@
# Copyright (c) 2017, Frappe Technologies and Contributors
# License: MIT. See LICENSE
import frappe
-from frappe.tests import IntegrationTestCase, UnitTestCase
-
-
-class UnitTestLetterHead(UnitTestCase):
- """
- Unit tests for LetterHead.
- Use this class for testing individual functions and methods.
- """
-
- pass
+from frappe.tests import IntegrationTestCase
class TestLetterHead(IntegrationTestCase):
diff --git a/frappe/printing/doctype/network_printer_settings/test_network_printer_settings.py b/frappe/printing/doctype/network_printer_settings/test_network_printer_settings.py
index 79aba2afd4..9671503a2f 100644
--- a/frappe/printing/doctype/network_printer_settings/test_network_printer_settings.py
+++ b/frappe/printing/doctype/network_printer_settings/test_network_printer_settings.py
@@ -2,16 +2,7 @@
# See license.txt
# import frappe
-from frappe.tests import IntegrationTestCase, UnitTestCase
-
-
-class UnitTestNetworkPrinterSettings(UnitTestCase):
- """
- Unit tests for NetworkPrinterSettings.
- Use this class for testing individual functions and methods.
- """
-
- pass
+from frappe.tests import IntegrationTestCase
class TestNetworkPrinterSettings(IntegrationTestCase):
diff --git a/frappe/printing/doctype/print_format/print_format.py b/frappe/printing/doctype/print_format/print_format.py
index 4e5029944b..5cf7c1e7e4 100644
--- a/frappe/printing/doctype/print_format/print_format.py
+++ b/frappe/printing/doctype/print_format/print_format.py
@@ -142,7 +142,7 @@ class PrintFormat(Document):
@frappe.whitelist()
def make_default(name):
"""Set print format as default"""
- frappe.has_permission("Print Format", "write")
+ frappe.has_permission("Print Format", "write", throw=True)
print_format = frappe.get_doc("Print Format", name)
diff --git a/frappe/printing/doctype/print_format/test_print_format.py b/frappe/printing/doctype/print_format/test_print_format.py
index 5bc68d0491..ac8ee764a8 100644
--- a/frappe/printing/doctype/print_format/test_print_format.py
+++ b/frappe/printing/doctype/print_format/test_print_format.py
@@ -6,21 +6,12 @@ import unittest
from typing import TYPE_CHECKING
import frappe
-from frappe.tests import IntegrationTestCase, UnitTestCase
+from frappe.tests import IntegrationTestCase
if TYPE_CHECKING:
from frappe.printing.doctype.print_format.print_format import PrintFormat
-class UnitTestPrintFormat(UnitTestCase):
- """
- Unit tests for PrintFormat.
- Use this class for testing individual functions and methods.
- """
-
- pass
-
-
class TestPrintFormat(IntegrationTestCase):
def test_print_user(self, style=None):
print_html = frappe.get_print("User", "Administrator", style=style)
diff --git a/frappe/printing/doctype/print_format_field_template/test_print_format_field_template.py b/frappe/printing/doctype/print_format_field_template/test_print_format_field_template.py
index 503cf0774d..40ee2f19af 100644
--- a/frappe/printing/doctype/print_format_field_template/test_print_format_field_template.py
+++ b/frappe/printing/doctype/print_format_field_template/test_print_format_field_template.py
@@ -2,16 +2,7 @@
# See license.txt
# import frappe
-from frappe.tests import IntegrationTestCase, UnitTestCase
-
-
-class UnitTestPrintFormatFieldTemplate(UnitTestCase):
- """
- Unit tests for PrintFormatFieldTemplate.
- Use this class for testing individual functions and methods.
- """
-
- pass
+from frappe.tests import IntegrationTestCase
class TestPrintFormatFieldTemplate(IntegrationTestCase):
diff --git a/frappe/printing/doctype/print_heading/test_print_heading.py b/frappe/printing/doctype/print_heading/test_print_heading.py
index 3011e20591..67b4371681 100644
--- a/frappe/printing/doctype/print_heading/test_print_heading.py
+++ b/frappe/printing/doctype/print_heading/test_print_heading.py
@@ -1,16 +1,7 @@
# Copyright (c) 2017, Frappe Technologies and Contributors
# License: MIT. See LICENSE
import frappe
-from frappe.tests import IntegrationTestCase, UnitTestCase
-
-
-class UnitTestPrintHeading(UnitTestCase):
- """
- Unit tests for PrintHeading.
- Use this class for testing individual functions and methods.
- """
-
- pass
+from frappe.tests import IntegrationTestCase
class TestPrintHeading(IntegrationTestCase):
diff --git a/frappe/printing/doctype/print_settings/print_settings.py b/frappe/printing/doctype/print_settings/print_settings.py
index 4ca4b3736e..dbb19519a9 100644
--- a/frappe/printing/doctype/print_settings/print_settings.py
+++ b/frappe/printing/doctype/print_settings/print_settings.py
@@ -75,9 +75,4 @@ class PrintSettings(Document):
@frappe.whitelist()
def is_print_server_enabled():
- if not hasattr(frappe.local, "enable_print_server"):
- frappe.local.enable_print_server = cint(
- frappe.db.get_single_value("Print Settings", "enable_print_server")
- )
-
- return frappe.local.enable_print_server
+ return frappe.get_single_value("Print Settings", "enable_print_server")
diff --git a/frappe/printing/doctype/print_settings/test_print_settings.py b/frappe/printing/doctype/print_settings/test_print_settings.py
index a699c5aaf7..6b75085d6a 100644
--- a/frappe/printing/doctype/print_settings/test_print_settings.py
+++ b/frappe/printing/doctype/print_settings/test_print_settings.py
@@ -1,15 +1,6 @@
# Copyright (c) 2018, Frappe Technologies and Contributors
# License: MIT. See LICENSE
-from frappe.tests import IntegrationTestCase, UnitTestCase
-
-
-class UnitTestPrintSettings(UnitTestCase):
- """
- Unit tests for PrintSettings.
- Use this class for testing individual functions and methods.
- """
-
- pass
+from frappe.tests import IntegrationTestCase
class TestPrintSettings(IntegrationTestCase):
diff --git a/frappe/printing/doctype/print_style/test_print_style.py b/frappe/printing/doctype/print_style/test_print_style.py
index bfbf172279..d25f7d5768 100644
--- a/frappe/printing/doctype/print_style/test_print_style.py
+++ b/frappe/printing/doctype/print_style/test_print_style.py
@@ -1,16 +1,7 @@
# Copyright (c) 2017, Frappe Technologies and Contributors
# License: MIT. See LICENSE
import frappe
-from frappe.tests import IntegrationTestCase, UnitTestCase
-
-
-class UnitTestPrintStyle(UnitTestCase):
- """
- Unit tests for PrintStyle.
- Use this class for testing individual functions and methods.
- """
-
- pass
+from frappe.tests import IntegrationTestCase
class TestPrintStyle(IntegrationTestCase):
diff --git a/frappe/public/icons/lucide.svg b/frappe/public/icons/lucide.svg
index b9bbb03158..0e5eab1451 100644
--- a/frappe/public/icons/lucide.svg
+++ b/frappe/public/icons/lucide.svg
@@ -8,6 +8,14 @@
+
+
+
+
+
+
+
+
diff --git a/frappe/public/icons/timeless/icons.svg b/frappe/public/icons/timeless/icons.svg
index b8dbde9d94..b8de8f59bc 100644
--- a/frappe/public/icons/timeless/icons.svg
+++ b/frappe/public/icons/timeless/icons.svg
@@ -60,6 +60,14 @@ Tip: use lucide.svg in /icons for all downloaded icons
+
+
+
+
+
+
+
+
@@ -396,7 +404,11 @@ Tip: use lucide.svg in /icons for all downloaded icons
-
+
+
+
+
+
@@ -728,14 +740,6 @@ Tip: use lucide.svg in /icons for all downloaded icons
-
-
-
-
-
-
-
-
@@ -978,10 +982,20 @@ Tip: use lucide.svg in /icons for all downloaded icons
+
+
+
+
+
+
+
+
+
+
diff --git a/frappe/public/js/frappe/desk.js b/frappe/public/js/frappe/desk.js
index e4fe8d1573..6ff35c91e8 100644
--- a/frappe/public/js/frappe/desk.js
+++ b/frappe/public/js/frappe/desk.js
@@ -182,6 +182,7 @@ frappe.Application = class Application {
}
frappe.router.on("change", () => {
$(".tooltip").hide();
+ if (frappe.frappe_toolbar && frappe.is_mobile()) frappe.frappe_toolbar.show_app_logo();
});
}
diff --git a/frappe/public/js/frappe/form/controls/text_editor.js b/frappe/public/js/frappe/form/controls/text_editor.js
index 61cc658b1f..582c6cace7 100644
--- a/frappe/public/js/frappe/form/controls/text_editor.js
+++ b/frappe/public/js/frappe/form/controls/text_editor.js
@@ -286,7 +286,7 @@ frappe.ui.form.ControlTextEditor = class ControlTextEditor extends frappe.ui.for
get_toolbar_options() {
return [
- [{ header: [1, 2, 3, false] }],
+ [{ header: [1, 2, 3, 4, 5, 6, false] }],
[{ size: font_sizes }],
["bold", "italic", "underline", "strike", "clean"],
[{ color: [] }, { background: [] }],
diff --git a/frappe/public/js/frappe/form/footer/form_timeline.js b/frappe/public/js/frappe/form/footer/form_timeline.js
index f541733616..7a398357a4 100644
--- a/frappe/public/js/frappe/form/footer/form_timeline.js
+++ b/frappe/public/js/frappe/form/footer/form_timeline.js
@@ -529,10 +529,28 @@ class FormTimeline extends BaseTimeline {
).click(() => {
this.compose_mail(communication_doc, true);
});
- actions.append(reply);
- actions.append(reply_all);
+ if (frappe.is_mobile()) {
+ this.add_dropdown_item(communication_box, [reply, reply_all]);
+ } else {
+ actions.append(reply);
+ actions.append(reply_all);
+ }
+ }
+ add_dropdown_item(timeline_box, menu_items) {
+ let more_actions = timeline_box.find(".more-actions > .dropdown-menu > li");
+ menu_items.forEach((m) => {
+ let action_name = m[0].classList[1];
+ let formatted_action_name =
+ String(action_name).charAt(0).toUpperCase() + String(action_name).slice(1);
+ m.empty();
+ m.append(
+ __("{0}", [frappe.utils.to_title_case(formatted_action_name.replace("-", " "))])
+ );
+ m.removeClass();
+ m.addClass("dropdown-item");
+ more_actions.append(m);
+ });
}
-
compose_mail(communication_doc = null, reply_all = false) {
const args = {
doc: this.frm.doc,
@@ -646,11 +664,11 @@ class FormTimeline extends BaseTimeline {
let edit_button = $();
let current_user = frappe.session.user;
if (["Administrator", doc.owner].includes(current_user)) {
- edit_button = $(`