Explorar el Código

Merge branch 'develop' into encrypt-otp-secrets

version-14
Sagar Vora hace 2 años
committed by GitHub
padre
commit
d6f3e2935f
No se encontró ninguna clave conocida en la base de datos para esta firma ID de clave GPG: 4AEE18F83AFDEB23
Se han modificado 63 ficheros con 552 adiciones y 529 borrados
  1. +1
    -1
      .editorconfig
  2. +1
    -1
      .github/helper/roulette.py
  3. +11
    -9
      .github/workflows/patch-mariadb-tests.yml
  4. +12
    -2
      frappe/core/doctype/comment/comment.json
  5. +2
    -1
      frappe/core/doctype/communication/mixins.py
  6. +9
    -3
      frappe/core/doctype/doctype/doctype.js
  7. +3
    -4
      frappe/core/doctype/doctype/doctype.py
  8. +0
    -8
      frappe/core/doctype/feedback/feedback.js
  9. +0
    -73
      frappe/core/doctype/feedback/feedback.json
  10. +0
    -9
      frappe/core/doctype/feedback/feedback.py
  11. +0
    -42
      frappe/core/doctype/feedback/test_feedback.py
  12. +1
    -1
      frappe/core/doctype/sms_settings/sms_settings.py
  13. +1
    -1
      frappe/core/doctype/system_settings/system_settings.py
  14. +3
    -3
      frappe/core/doctype/user/user.py
  15. +5
    -6
      frappe/core/doctype/version/version_view.html
  16. +2
    -4
      frappe/hooks.py
  17. +3
    -3
      frappe/integrations/doctype/dropbox_settings/dropbox_settings.py
  18. +1
    -1
      frappe/integrations/doctype/google_drive/google_drive.py
  19. +3
    -1
      frappe/integrations/doctype/oauth_provider_settings/oauth_provider_settings.py
  20. +2
    -2
      frappe/integrations/doctype/s3_backup_settings/s3_backup_settings.py
  21. +19
    -2
      frappe/model/naming.py
  22. +1
    -0
      frappe/patches.txt
  23. +1
    -1
      frappe/patches/v11_0/set_dropbox_file_backup.py
  24. +30
    -0
      frappe/patches/v14_0/setup_likes_from_feedback.py
  25. +2
    -2
      frappe/public/js/frappe/form/controls/datepicker_i18n.js
  26. +2
    -1
      frappe/public/js/frappe/form/dashboard.js
  27. +1
    -1
      frappe/public/js/frappe/form/formatters.js
  28. +0
    -15
      frappe/public/js/frappe/list/base_list.js
  29. +1
    -4
      frappe/public/js/frappe/list/list_view.js
  30. +1
    -1
      frappe/public/js/frappe/utils/diffview.js
  31. +38
    -2
      frappe/public/js/frappe/utils/utils.js
  32. +4
    -3
      frappe/public/js/frappe/views/reports/query_report.js
  33. +2
    -1
      frappe/public/js/frappe/views/reports/report_utils.js
  34. +2
    -1
      frappe/public/js/frappe/views/reports/report_view.js
  35. +5
    -1
      frappe/public/scss/common/css_variables.scss
  36. +5
    -1
      frappe/public/scss/desk/dark.scss
  37. +8
    -12
      frappe/public/scss/desk/global.scss
  38. +1
    -1
      frappe/templates/includes/comments/comment.html
  39. +3
    -4
      frappe/templates/includes/comments/comments.html
  40. +8
    -7
      frappe/templates/includes/comments/comments.py
  41. +0
    -0
      frappe/templates/includes/feedback/__init__.py
  42. +0
    -55
      frappe/templates/includes/feedback/feedback.py
  43. +0
    -0
      frappe/templates/includes/likes/__init__.py
  44. +11
    -13
      frappe/templates/includes/likes/likes.html
  45. +77
    -0
      frappe/templates/includes/likes/likes.py
  46. +1
    -1
      frappe/templates/pages/integrations/razorpay_checkout.py
  47. +27
    -0
      frappe/tests/test_naming.py
  48. +138
    -153
      frappe/translations/ru.csv
  49. +9
    -13
      frappe/twofactor.py
  50. +1
    -1
      frappe/utils/data.py
  51. +1
    -0
      frappe/utils/safe_exec.py
  52. +9
    -9
      frappe/website/doctype/blog_post/blog_post.json
  53. +25
    -27
      frappe/website/doctype/blog_post/blog_post.py
  54. +16
    -3
      frappe/website/doctype/blog_post/templates/blog_post.html
  55. +23
    -0
      frappe/website/doctype/blog_post/test_blog_post.py
  56. +9
    -9
      frappe/website/doctype/blog_settings/blog_settings.json
  57. +2
    -2
      frappe/website/doctype/blog_settings/blog_settings.py
  58. +1
    -1
      frappe/website/doctype/web_page_view/web_page_view.py
  59. +1
    -1
      frappe/website/doctype/website_settings/google_indexing.py
  60. +1
    -1
      frappe/www/contact.py
  61. +1
    -1
      package.json
  62. +1
    -0
      pyproject.toml
  63. +4
    -4
      yarn.lock

+ 1
- 1
.editorconfig Ver fichero

@@ -9,6 +9,6 @@ trim_trailing_whitespace = true
charset = utf-8

# python, js indentation settings
[{*.py,*.js,*.vue}]
[{*.py,*.js,*.vue,*.css,*.scss,*.html}]
indent_style = tab
indent_size = 4

+ 1
- 1
.github/helper/roulette.py Ver fichero

@@ -46,7 +46,7 @@ def is_ci(file):
return ".github" in file

def is_frontend_code(file):
return file.lower().endswith((".css", ".scss", ".less", ".sass", ".styl", ".js", ".ts", ".vue"))
return file.lower().endswith((".css", ".scss", ".less", ".sass", ".styl", ".js", ".ts", ".vue", ".html"))

def is_docs(file):
regex = re.compile(r'\.(md|png|jpg|jpeg|csv|svg)$|^.github|LICENSE')


+ 11
- 9
.github/workflows/patch-mariadb-tests.yml Ver fichero

@@ -30,26 +30,28 @@ jobs:
- name: Clone
uses: actions/checkout@v3

- name: Check if build should be run
id: check-build
run: |
python "${GITHUB_WORKSPACE}/.github/helper/roulette.py"
env:
TYPE: "server"
PR_NUMBER: ${{ github.event.number }}
REPO_NAME: ${{ github.repository }}

- name: Setup Python
if: ${{ steps.check-build.outputs.build == 'strawberry' }}
uses: "gabrielfalcao/pyenv-action@v10"
with:
versions: 3.10:latest, 3.7:latest

- name: Setup Node
if: ${{ steps.check-build.outputs.build == 'strawberry' }}
uses: actions/setup-node@v3
with:
node-version: 14
check-latest: true

- name: Check if build should be run
id: check-build
run: |
python "${GITHUB_WORKSPACE}/.github/helper/roulette.py"
env:
TYPE: "server"
PR_NUMBER: ${{ github.event.number }}
REPO_NAME: ${{ github.repository }}

- name: Add to Hosts
if: ${{ steps.check-build.outputs.build == 'strawberry' }}
run: echo "127.0.0.1 test_site" | sudo tee -a /etc/hosts


+ 12
- 2
frappe/core/doctype/comment/comment.json Ver fichero

@@ -1,4 +1,5 @@
{
"actions": [],
"creation": "2019-02-07 10:10:46.845678",
"doctype": "DocType",
"editable_grid": 1,
@@ -17,7 +18,8 @@
"link_name",
"reference_owner",
"section_break_10",
"content"
"content",
"ip_address"
],
"fields": [
{
@@ -102,9 +104,16 @@
"ignore_xss_filter": 1,
"in_list_view": 1,
"label": "Content"
},
{
"fieldname": "ip_address",
"fieldtype": "Data",
"hidden": 1,
"label": "IP Address"
}
],
"modified": "2019-09-02 21:00:10.784787",
"links": [],
"modified": "2022-07-12 17:35:31.774137",
"modified_by": "Administrator",
"module": "Core",
"name": "Comment",
@@ -138,6 +147,7 @@
"quick_entry": 1,
"sort_field": "modified",
"sort_order": "DESC",
"states": [],
"title_field": "comment_type",
"track_changes": 1
}

+ 2
- 1
frappe/core/doctype/communication/mixins.py Ver fichero

@@ -73,7 +73,8 @@ class CommunicationEmailMixin:
if include_sender:
cc.append(self.sender_mailid)
if is_inbound_mail_communcation:
cc.append(self.get_owner())
if (doc_owner := self.get_owner()) not in frappe.STANDARD_USERS:
cc.append(doc_owner)
cc = set(cc) - {self.sender_mailid}
cc.update(self.get_assignees())



+ 9
- 3
frappe/core/doctype/doctype/doctype.js Ver fichero

@@ -46,9 +46,7 @@ frappe.ui.form.on('DocType', {
}

if(frm.is_new()) {
if (!(frm.doc.permissions && frm.doc.permissions.length)) {
frm.add_child('permissions', {role: 'System Manager'});
}
frm.events.set_default_permission(frm);
} else {
frm.toggle_enable("engine", 0);
}
@@ -65,6 +63,14 @@ frappe.ui.form.on('DocType', {
if (frm.doc.istable && frm.is_new()) {
frm.set_value('autoname', 'autoincrement');
frm.set_value('allow_rename', 0);
} else if (!frm.doc.istable && !frm.is_new()) {
frm.events.set_default_permission(frm);
}
},

set_default_permission: (frm) => {
if (!(frm.doc.permissions && frm.doc.permissions.length)) {
frm.add_child('permissions', {role: 'System Manager'});
}
},
});


+ 3
- 4
frappe/core/doctype/doctype/doctype.py Ver fichero

@@ -181,10 +181,6 @@ class DocType(Document):
)
)

def after_insert(self):
# clear user cache so that on the next reload this doctype is included in boot
clear_user_cache(frappe.session.user)

def set_defaults_for_single_and_table(self):
if self.issingle:
self.allow_import = 0
@@ -412,6 +408,9 @@ class DocType(Document):
delete_notification_count_for(doctype=self.name)
frappe.clear_cache(doctype=self.name)

# clear user cache so that on the next reload this doctype is included in boot
clear_user_cache(frappe.session.user)

if not frappe.flags.in_install and hasattr(self, "before_update"):
self.sync_global_search()



+ 0
- 8
frappe/core/doctype/feedback/feedback.js Ver fichero

@@ -1,8 +0,0 @@
// Copyright (c) 2021, Frappe Technologies and contributors
// For license information, please see license.txt

frappe.ui.form.on('Feedback', {
// refresh: function(frm) {

// }
});

+ 0
- 73
frappe/core/doctype/feedback/feedback.json Ver fichero

@@ -1,73 +0,0 @@
{
"actions": [],
"creation": "2021-06-03 19:02:55.328423",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"reference_doctype",
"reference_name",
"column_break_3",
"like",
"ip_address"
],
"fields": [
{
"fieldname": "column_break_3",
"fieldtype": "Column Break"
},
{
"fieldname": "reference_doctype",
"fieldtype": "Select",
"in_list_view": 1,
"label": "Reference Document Type",
"options": "\nBlog Post"
},
{
"fieldname": "reference_name",
"fieldtype": "Dynamic Link",
"in_list_view": 1,
"label": "Reference Name",
"options": "reference_doctype",
"reqd": 1
},
{
"fieldname": "ip_address",
"fieldtype": "Data",
"hidden": 1,
"label": "IP Address",
"read_only": 1
},
{
"default": "0",
"fieldname": "like",
"fieldtype": "Check",
"label": "Like"
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2021-11-10 20:53:21.255593",
"modified_by": "Administrator",
"module": "Core",
"name": "Feedback",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"sort_field": "modified",
"sort_order": "DESC",
"title_field": "reference_name",
"track_changes": 1
}

+ 0
- 9
frappe/core/doctype/feedback/feedback.py Ver fichero

@@ -1,9 +0,0 @@
# Copyright (c) 2021, Frappe Technologies and contributors
# License: MIT. See LICENSE

# import frappe
from frappe.model.document import Document


class Feedback(Document):
pass

+ 0
- 42
frappe/core/doctype/feedback/test_feedback.py Ver fichero

@@ -1,42 +0,0 @@
# Copyright (c) 2021, Frappe Technologies and Contributors
# License: MIT. See LICENSE

import unittest

import frappe


class TestFeedback(unittest.TestCase):
def tearDown(self):
frappe.form_dict.reference_doctype = None
frappe.form_dict.reference_name = None
frappe.form_dict.like = None
frappe.local.request_ip = None

def test_feedback_creation_updation(self):
from frappe.website.doctype.blog_post.test_blog_post import make_test_blog

test_blog = make_test_blog()

frappe.db.delete("Feedback", {"reference_doctype": "Blog Post"})

from frappe.templates.includes.feedback.feedback import give_feedback

frappe.form_dict.reference_doctype = "Blog Post"
frappe.form_dict.reference_name = test_blog.name
frappe.form_dict.like = True
frappe.local.request_ip = "127.0.0.1"

feedback = give_feedback()

self.assertEqual(feedback.like, True)

frappe.form_dict.like = False

updated_feedback = give_feedback()

self.assertEqual(updated_feedback.like, False)

frappe.db.delete("Feedback", {"reference_doctype": "Blog Post"})

test_blog.delete()

+ 1
- 1
frappe/core/doctype/sms_settings/sms_settings.py Ver fichero

@@ -63,7 +63,7 @@ def send_sms(receiver_list, msg, sender_name="", success_msg=True):
"success_msg": success_msg,
}

if frappe.db.get_value("SMS Settings", None, "sms_gateway_url"):
if frappe.db.get_single_value("SMS Settings", "sms_gateway_url"):
send_via_gateway(arg)
else:
msgprint(_("Please Update SMS Settings"))


+ 1
- 1
frappe/core/doctype/system_settings/system_settings.py Ver fichero

@@ -28,7 +28,7 @@ class SystemSettings(Document):

if self.enable_two_factor_auth:
if self.two_factor_method == "SMS":
if not frappe.db.get_value("SMS Settings", None, "sms_gateway_url"):
if not frappe.db.get_single_value("SMS Settings", "sms_gateway_url"):
frappe.throw(
_("Please setup SMS before setting it as an authentication method, via SMS Settings")
)


+ 3
- 3
frappe/core/doctype/user/user.py Ver fichero

@@ -611,10 +611,10 @@ class User(Document):
"""

login_with_mobile = cint(
frappe.db.get_value("System Settings", "System Settings", "allow_login_using_mobile_number")
frappe.db.get_single_value("System Settings", "allow_login_using_mobile_number")
)
login_with_username = cint(
frappe.db.get_value("System Settings", "System Settings", "allow_login_using_user_name")
frappe.db.get_single_value("System Settings", "allow_login_using_user_name")
)

or_filters = [{"name": user_name}]
@@ -861,7 +861,7 @@ def sign_up(email, full_name, redirect_to):
user.insert()

# set default signup role as per Portal Settings
default_role = frappe.db.get_value("Portal Settings", None, "default_role")
default_role = frappe.db.get_single_value("Portal Settings", "default_role")
if default_role:
user.add_roles(default_role)



+ 5
- 6
frappe/core/doctype/version/version_view.html Ver fichero

@@ -18,8 +18,8 @@
{% for item in data.changed %}
<tr>
<td>{{ frappe.meta.get_label(doc.ref_doctype, item[0]) }}</td>
<td class="danger">{{ item[1] }}</td>
<td class="success">{{ item[2] }}</td>
<td class="diff-remove">{{ item[1] }}</td>
<td class="diff-add">{{ item[2] }}</td>
</tr>
{% endfor %}
</tbody>
@@ -43,8 +43,7 @@
{% for item in values %}
<tr>
<td>{{ frappe.meta.get_label(doc.ref_doctype, item[0]) }}</td>
<td class="{{
key==="added" ? __("success") : __("danger") }}">
<td class="{{ key==="added" ? "diff-add" : "diff-remove" }}">
{% var item_keys = Object.keys(item[1]).sort(); %}
<table class="table table-bordered">
<tbody>
@@ -86,8 +85,8 @@
<td>{{ frappe.meta.get_label(doc.ref_doctype, table_info[0]) }}</td>
<td>{{ table_info[1] }}</td>
<td>{{ item[0] }}</td>
<td class="danger">{{ item[1] }}</td>
<td class="success">{{ item[2] }}</td>
<td class="diff-remove">{{ item[1] }}</td>
<td class="diff-add">{{ item[2] }}</td>
</tr>
{% endfor %}
{% endfor %}


+ 2
- 4
frappe/hooks.py Ver fichero

@@ -180,12 +180,10 @@ doc_events = {
"on_update": "frappe.integrations.doctype.google_contacts.google_contacts.update_contacts_to_google_contacts",
},
"DocType": {
"after_insert": "frappe.cache_manager.build_domain_restriced_doctype_cache",
"after_save": "frappe.cache_manager.build_domain_restriced_doctype_cache",
"on_update": "frappe.cache_manager.build_domain_restriced_doctype_cache",
},
"Page": {
"after_insert": "frappe.cache_manager.build_domain_restriced_page_cache",
"after_save": "frappe.cache_manager.build_domain_restriced_page_cache",
"on_update": "frappe.cache_manager.build_domain_restriced_page_cache",
},
}



+ 3
- 3
frappe/integrations/doctype/dropbox_settings/dropbox_settings.py Ver fichero

@@ -62,21 +62,21 @@ def take_backups_weekly():


def take_backups_if(freq):
if frappe.db.get_value("Dropbox Settings", None, "backup_frequency") == freq:
if frappe.db.get_single_value("Dropbox Settings", "backup_frequency") == freq:
take_backup_to_dropbox()


def take_backup_to_dropbox(retry_count=0, upload_db_backup=True):
did_not_upload, error_log = [], []
try:
if cint(frappe.db.get_value("Dropbox Settings", None, "enabled")):
if cint(frappe.db.get_single_value("Dropbox Settings", "enabled")):
validate_file_size()

did_not_upload, error_log = backup_to_dropbox(upload_db_backup)
if did_not_upload:
raise Exception

if cint(frappe.db.get_value("Dropbox Settings", None, "send_email_for_successful_backup")):
if cint(frappe.db.get_single_value("Dropbox Settings", "send_email_for_successful_backup")):
send_email(True, "Dropbox", "Dropbox Settings", "send_notifications_to")
except JobTimeoutException:
if retry_count < 2:


+ 1
- 1
frappe/integrations/doctype/google_drive/google_drive.py Ver fichero

@@ -48,7 +48,7 @@ def authorize_access(reauthorize=False, code=None):
"""

oauth_code = (
frappe.db.get_value("Google Drive", "Google Drive", "authorization_code") if not code else code
frappe.db.get_single_value("Google Drive", "authorization_code") if not code else code
)
oauth_obj = GoogleOAuth("drive")



+ 3
- 1
frappe/integrations/doctype/oauth_provider_settings/oauth_provider_settings.py Ver fichero

@@ -14,7 +14,9 @@ def get_oauth_settings():
"""Returns oauth settings"""
out = frappe._dict(
{
"skip_authorization": frappe.db.get_value("OAuth Provider Settings", None, "skip_authorization")
"skip_authorization": frappe.db.get_single_value(
"OAuth Provider Settings", "skip_authorization"
)
}
)



+ 2
- 2
frappe/integrations/doctype/s3_backup_settings/s3_backup_settings.py Ver fichero

@@ -76,8 +76,8 @@ def take_backups_monthly():


def take_backups_if(freq):
if cint(frappe.db.get_value("S3 Backup Settings", None, "enabled")):
if frappe.db.get_value("S3 Backup Settings", None, "frequency") == freq:
if cint(frappe.db.get_single_value("S3 Backup Settings", "enabled")):
if frappe.db.get_single_value("S3 Backup Settings", "frequency") == freq:
take_backups_s3()




+ 19
- 2
frappe/model/naming.py Ver fichero

@@ -1,6 +1,7 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: MIT. See LICENSE

import datetime
import re
from typing import TYPE_CHECKING, Callable, Optional

@@ -23,6 +24,17 @@ NAMING_SERIES_PATTERN = re.compile(r"^[\w\- \/.#{}]+$", re.UNICODE)
BRACED_PARAMS_PATTERN = re.compile(r"(\{[\w | #]+\})")


# Types that can be using in naming series fields
NAMING_SERIES_PART_TYPES = (
int,
str,
datetime.datetime,
datetime.date,
datetime.time,
datetime.timedelta,
)


class InvalidNamingSeriesError(frappe.ValidationError):
pass

@@ -298,6 +310,9 @@ def parse_naming_series(
series_set = False
today = now_datetime()
for e in parts:
if not e:
continue

part = ""
if e.startswith("#"):
if not series_set:
@@ -320,14 +335,16 @@ def parse_naming_series(
part = frappe.defaults.get_user_default("fiscal_year")
elif e.startswith("{") and doc:
e = e.replace("{", "").replace("}", "")
part = (cstr(doc.get(e)) or "").strip()
part = doc.get(e)
elif doc and doc.get(e):
part = (cstr(doc.get(e)) or "").strip()
part = doc.get(e)
else:
part = e

if isinstance(part, str):
name += part
elif isinstance(part, NAMING_SERIES_PART_TYPES):
name += cstr(part).strip()

return name



+ 1
- 0
frappe/patches.txt Ver fichero

@@ -193,6 +193,7 @@ frappe.patches.v14_0.reset_creation_datetime
frappe.patches.v14_0.remove_is_first_startup
frappe.patches.v14_0.clear_long_pending_stale_logs
frappe.patches.v14_0.log_settings_migration
frappe.patches.v14_0.setup_likes_from_feedback

[post_model_sync]
frappe.patches.v14_0.drop_data_import_legacy


+ 1
- 1
frappe/patches/v11_0/set_dropbox_file_backup.py Ver fichero

@@ -4,6 +4,6 @@ from frappe.utils import cint

def execute():
frappe.reload_doctype("Dropbox Settings")
check_dropbox_enabled = cint(frappe.db.get_value("Dropbox Settings", None, "enabled"))
check_dropbox_enabled = cint(frappe.db.get_single_value("Dropbox Settings", "enabled"))
if check_dropbox_enabled == 1:
frappe.db.set_value("Dropbox Settings", None, "file_backup", 1)

+ 30
- 0
frappe/patches/v14_0/setup_likes_from_feedback.py Ver fichero

@@ -0,0 +1,30 @@
import frappe


def execute():
frappe.reload_doctype("Comment")

if frappe.db.count("Feedback") > 20000:
frappe.db.auto_commit_on_many_writes = True

for feedback in frappe.get_all("Feedback", fields=["*"]):
if feedback.like:
new_comment = frappe.new_doc("Comment")
new_comment.comment_type = "Like"
new_comment.comment_email = feedback.owner
new_comment.content = "Liked by: " + feedback.owner
new_comment.reference_doctype = feedback.reference_doctype
new_comment.reference_name = feedback.reference_name
new_comment.creation = feedback.creation
new_comment.modified = feedback.modified
new_comment.owner = feedback.owner
new_comment.modified_by = feedback.modified_by
new_comment.ip_address = feedback.ip_address
new_comment.db_insert()

if frappe.db.auto_commit_on_many_writes:
frappe.db.auto_commit_on_many_writes = False

# clean up
frappe.db.delete("Feedback")
frappe.db.commit()

+ 2
- 2
frappe/public/js/frappe/form/controls/datepicker_i18n.js Ver fichero

@@ -22,10 +22,10 @@ import "air-datepicker/dist/js/i18n/datepicker.zh.js";
months: ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'اكتوبر', 'نوفمبر', 'ديسمبر'],
monthsShort: ['يناير', 'فبراير', 'مارس', 'أبريل', 'مايو', 'يونيو', 'يوليو', 'أغسطس', 'سبتمبر', 'اكتوبر', 'نوفمبر', 'ديسمبر'],
today: 'اليوم',
clear: 'Clear',
clear: 'حذف',
dateFormat: 'dd/mm/yyyy',
timeFormat: 'hh:ii aa',
firstDay: 0
firstDay: 6
};
})(jQuery);



+ 2
- 1
frappe/public/js/frappe/form/dashboard.js Ver fichero

@@ -554,7 +554,8 @@ frappe.ui.form.Dashboard = class FormDashboard {
colors: ['green'],
truncateLegends: 1,
axisOptions: {
shortenYAxisNumbers: 1
shortenYAxisNumbers: 1,
numberFormatter: frappe.utils.format_chart_axis_number,
}
});
this.show();


+ 1
- 1
frappe/public/js/frappe/form/formatters.js Ver fichero

@@ -26,7 +26,7 @@ frappe.form.formatters = {
if (df) {
const std_df = frappe.meta.docfield_map[df.parent] && frappe.meta.docfield_map[df.parent][df.fieldname];
if (std_df && std_df.formatter && typeof std_df.formatter==='function') {
value = std_df.formatter(value);
value = std_df.formatter(value, df);
}
}
return value;


+ 0
- 15
frappe/public/js/frappe/list/base_list.js Ver fichero

@@ -764,10 +764,6 @@ class FilterArea {

const doctype_fields = this.list_view.meta.fields;
const title_field = this.list_view.meta.title_field;
const has_existing_filters = (
this.list_view.filters
&& this.list_view.filters.length > 0
);

fields = fields.concat(
doctype_fields
@@ -803,23 +799,12 @@ class FilterArea {
}
}

let default_value;

if (fieldtype === "Link" && !has_existing_filters) {
default_value = frappe.defaults.get_user_default(options);
}

if (["__default", "__global"].includes(default_value)) {
default_value = null;
}

return {
fieldtype: fieldtype,
label: __(df.label),
options: options,
fieldname: df.fieldname,
condition: condition,
default: default_value,
onchange: () => this.refresh_list_view(),
ignore_link_validation: fieldtype === "Dynamic Link",
is_filter: 1,


+ 1
- 4
frappe/public/js/frappe/list/list_view.js Ver fichero

@@ -87,10 +87,7 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList {
this.menu_items = this.menu_items.concat(this.get_menu_items());

// set filters from view_user_settings or list_settings
if (
this.view_user_settings.filters &&
this.view_user_settings.filters.length
) {
if (Array.isArray(this.view_user_settings.filters)) {
// Priority 1: view_user_settings
const saved_filters = this.view_user_settings.filters;
this.filters = this.validate_filters(saved_filters);


+ 1
- 1
frappe/public/js/frappe/utils/diffview.js Ver fichero

@@ -89,7 +89,7 @@ frappe.ui.DiffView = class DiffView {
} else if (line.startsWith("-")) {
line_class = "delete";
}
html += `<div class=${line_class}>${line}</div>`;
html += `<div class="${line_class} text-wrap">${line}</div>`;
});
return `<div class='diffview'>${html}</div>`;
}


+ 38
- 2
frappe/public/js/frappe/utils/utils.js Ver fichero

@@ -1145,7 +1145,12 @@ Object.assign(frappe.utils, {
{
divisor: 1.0e+5,
symbol: 'Lakh'
}],
},
{
divisor: 1.0e+3,
symbol: 'K',
}
],
'':
[{
divisor: 1.0e+12,
@@ -1205,7 +1210,8 @@ Object.assign(frappe.utils, {
axisOptions: {
xIsSeries: 1,
shortenYAxisNumbers: 1,
xAxisMode: 'tick'
xAxisMode: 'tick',
numberFormatter: frappe.utils.format_chart_axis_number,
}
};

@@ -1220,6 +1226,11 @@ Object.assign(frappe.utils, {
return new frappe.Chart(wrapper, chart_args);
},

format_chart_axis_number(label, country) {
const default_country = frappe.sys_defaults.country;
return frappe.utils.shorten_number(label, country || default_country, 3);
},

generate_route(item) {
const type = item.type.toLowerCase();
if (type === "doctype") {
@@ -1537,4 +1548,29 @@ Object.assign(frappe.utils, {
is_current_user(user) {
return user === frappe.session.user;
},

debug: {
watch_property(obj, prop, callback=console.trace) {
if (!frappe.boot.developer_mode) {
return;
}
console.warn("Adding property watcher, make sure to remove it after debugging.");

// Adapted from https://stackoverflow.com/a/11658693
// Reused under CC-BY-SA 4.0
// changes: variable names are changed for consistency with our codebase
const private_prop = "$_" + prop + "_$";
obj[private_prop] = obj[prop];

Object.defineProperty(obj, prop, {
get: function() {
return obj[private_prop];
},
set: function(value) {
callback();
obj[private_prop] = value;
},
});
},
}
});

+ 4
- 3
frappe/public/js/frappe/views/reports/query_report.js Ver fichero

@@ -623,6 +623,7 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList {

if (data.prepared_report) {
this.prepared_report = true;
this.prepared_report_document = data.doc
// If query_string contains prepared_report_name then set filters
// to match the mentioned prepared report doc and disable editing
if (query_params.prepared_report_name) {
@@ -943,10 +944,10 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList {
};
}
options.axisOptions = {
shortenYAxisNumbers: 1
shortenYAxisNumbers: 1,
numberFormatter: frappe.utils.format_chart_axis_number,
};
options.height = 280;

return options;
}

@@ -1800,7 +1801,7 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList {
}

toggle_nothing_to_show(flag) {
let message = this.prepared_report
let message = (this.prepared_report && !this.prepared_report_document)
? __('This is a background report. Please set the appropriate filters and then generate a new one.')
: this.get_no_result_message();



+ 2
- 1
frappe/public/js/frappe/views/reports/report_utils.js Ver fichero

@@ -30,7 +30,8 @@ frappe.report_utils = {
colors: colors,
axisOptions: {
shortenYAxisNumbers: 1,
xAxisMode: 'tick'
xAxisMode: 'tick',
numberFormatter: frappe.utils.format_chart_axis_number,
}
};



+ 2
- 1
frappe/public/js/frappe/views/reports/report_view.js Ver fichero

@@ -529,7 +529,8 @@ frappe.views.ReportView = class ReportView extends frappe.views.ListView {
truncateLegends: 1,
colors: ['#70E078', 'light-blue', 'orange', 'red'],
axisOptions: {
shortenYAxisNumbers: 1
shortenYAxisNumbers: 1,
numberFormatter: frappe.utils.format_chart_axis_number,
},
tooltipOptions: {
formatTooltipY: value => frappe.format(value, get_df(this.chart_args.y_axes[0]), { always_show_decimals: true, inline: true }, get_doc(value.doc))


+ 5
- 1
frappe/public/scss/common/css_variables.scss Ver fichero

@@ -134,7 +134,7 @@ $input-height: 28px !default;

--shadow-xs: rgba(0, 0, 0, 0.05) 0px 0.5px 0px 0px, rgba(0, 0, 0, 0.08) 0px 0px 0px 1px, rgba(0, 0, 0, 0.05) 0px 2px 4px 0px;
--shadow-sm: 0px 1px 2px rgba(25, 39, 52, 0.05), 0px 0px 4px rgba(25, 39, 52, 0.1);
--shadow-base: 0px 4px 8px rgba(25, 39, 52, 0.06), 0px 0px 4px rgba(25, 39, 52, 0.12);
--shadow-base: 0px 4px 8px rgba(25, 39, 52, 0.06), 0px 0px 4px rgba(25, 39, 52, 0.12);
--shadow-md: 0px 8px 14px rgba(25, 39, 52, 0.08), 0px 2px 6px rgba(25, 39, 52, 0.04);
--shadow-lg: 0px 18px 22px rgba(25, 39, 52, 0.1), 0px 1px 10px rgba(0, 0, 0, 0.06), 0px 0.5px 5px rgba(25, 39, 52, 0.04);

@@ -262,6 +262,10 @@ $input-height: 28px !default;
--checkbox-focus-shadow: 0 0 0 2px var(--gray-300);
--checkbox-gradient: linear-gradient(180deg, #4AC3F8 -124.51%, var(--primary) 100%);

// "diff" colors
--diff-added: var(--green-100);
--diff-removed: var(--red-100);

--right-arrow-svg: url("data: image/svg+xml;utf8, <svg width='6' height='8' viewBox='0 0 6 8' fill='none' xmlns='http://www.w3.org/2000/svg'><path d='M1.25 7.5L4.75 4L1.25 0.5' stroke='%231F272E' stroke-linecap='round' stroke-linejoin='round'/></svg>");
--left-arrow-svg: url("data: image/svg+xml;utf8, <svg width='6' height='8' viewBox='0 0 6 8' fill='none' xmlns='http://www.w3.org/2000/svg'><path d='M7.5 9.5L4 6l3.5-3.5' stroke='%231F272E' stroke-linecap='round' stroke-linejoin='round'></path></svg>");
}

+ 5
- 1
frappe/public/scss/desk/dark.scss Ver fichero

@@ -91,7 +91,11 @@

--highlight-shadow: 1px 1px 10px var(--blue-900), 0px 0px 4px var(--blue-500);

--shadow-base: 0px 4px 8px rgba(114, 176, 233, 0.06), 0px 0px 4px rgba(112, 172, 228, 0.12);
--shadow-base: 0px 4px 8px rgba(114, 176, 233, 0.06), 0px 0px 4px rgba(112, 172, 228, 0.12);

// "diff" colors
--diff-added: var(--green-800);
--diff-removed: var(--red-800);

// input
--input-disabled-bg: none;


+ 8
- 12
frappe/public/scss/desk/global.scss Ver fichero

@@ -579,22 +579,18 @@ details > summary:focus {
color: var(--text-color);
}

.diffview .insert {
background-color: var(--green-100);
.diffview .insert,
.diff-add {
background-color: var(--diff-added);
}

.diffview .delete {
background-color: var(--red-100);
.diffview .delete,
.diff-remove {
background-color: var(--diff-removed);
}

[data-theme="dark"] {
.diffview .insert {
background-color: var(--green-800);
}
.diffview .delete {
background-color: var(--red-800);
}
.chart-wrapper {
padding: 1em;
}

// REDESIGN TODO: Handling of broken images?


+ 1
- 1
frappe/templates/includes/comments/comment.html Ver fichero

@@ -13,6 +13,6 @@
{{ frappe.utils.pretty_date(comment.creation) }}
</span>
</div>
<div class="content">{{ frappe.utils.strip_html(comment.content) | markdown }}</div>
<div id="{{ comment.name }}" class="content">{{ frappe.utils.strip_html(comment.content) | markdown }}</div>
</div>
</div>

+ 3
- 4
frappe/templates/includes/comments/comments.html Ver fichero

@@ -57,7 +57,7 @@
<script>
frappe.ready(function() {
let guest_allowed = parseInt("{{ guest_allowed or 0}}");
let comment_count = "{{ comment_text }}";
let comment_count = "{{ comment_count }}";
let full_name = ""
let user_id = "";

@@ -88,9 +88,9 @@
}

let $comment_count = $(`
<div class="feedback-item">
<div class="feedback-item comments">
<span class="comment-icon">${frappe.utils.icon('small-message', 'md')}</span>
<span class="comment-count"></span>
<span class="comment-count">${comment_count}</span>
</div>
`);

@@ -127,7 +127,6 @@
}

$('.blog-feedback').append($comment_count);
$('.comment-count').text(comment_count);
$("#comment-form textarea").val("");

update_timeline_line_length('bottom');


+ 8
- 7
frappe/templates/includes/comments/comments.py Ver fichero

@@ -3,9 +3,8 @@
import re

import frappe
from frappe import _
from frappe import _, scrub
from frappe.rate_limiter import rate_limit
from frappe.utils import add_to_date, now
from frappe.utils.html_utils import clean_html
from frappe.website.doctype.blog_settings.blog_settings import get_comment_limit
from frappe.website.utils import clear_cache
@@ -42,11 +41,13 @@ def add_comment(comment, comment_email, comment_by, reference_doctype, reference
if route:
clear_cache(route)

content = (
comment.content
+ "<p><a href='{}/app/Form/Comment/{}' style='font-size: 80%'>{}</a></p>".format(
frappe.utils.get_request_site_address(), comment.name, _("View Comment")
)
if doc.get("route"):
url = f"{frappe.utils.get_request_site_address()}/{doc.route}#{comment.name}"
else:
url = f"{frappe.utils.get_request_site_address()}/app/{scrub(doc.doctype)}/{doc.name}#comment-{comment.name}"

content = comment.content + "<p><a href='{}' style='font-size: 80%'>{}</a></p>".format(
url, _("View Comment")
)

if doc.doctype == "Blog Post" and not doc.enable_email_notification:


+ 0
- 0
frappe/templates/includes/feedback/__init__.py Ver fichero


+ 0
- 55
frappe/templates/includes/feedback/feedback.py Ver fichero

@@ -1,55 +0,0 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: MIT. See LICENSE

import frappe
from frappe import _
from frappe.rate_limiter import rate_limit
from frappe.website.doctype.blog_settings.blog_settings import get_feedback_limit


@frappe.whitelist(allow_guest=True)
@rate_limit(key="reference_name", limit=get_feedback_limit, seconds=60 * 60)
def give_feedback(reference_doctype, reference_name, like):
like = frappe.parse_json(like)
ref_doc = frappe.get_doc(reference_doctype, reference_name)
if ref_doc.disable_feedback == 1:
return

filters = {
"owner": frappe.session.user,
"reference_doctype": reference_doctype,
"reference_name": reference_name,
}
d = frappe.get_all("Feedback", filters=filters, limit=1)
if d:
doc = frappe.get_doc("Feedback", d[0].name)
else:
doc = doc = frappe.new_doc("Feedback")
doc.reference_doctype = reference_doctype
doc.reference_name = reference_name
doc.ip_address = frappe.local.request_ip
doc.like = like
doc.save(ignore_permissions=True)

subject = _("Feedback on {0}: {1}").format(reference_doctype, reference_name)
ref_doc.enable_email_notification and send_mail(doc, subject)
return doc


def send_mail(feedback, subject):
doc = frappe.get_doc(feedback.reference_doctype, feedback.reference_name)
if feedback.like:
message = "<p>Hey, </p><p>You have received a ❤️ heart on your blog post <b>{}</b></p>".format(
feedback.reference_name
)
else:
return

# notify creator
frappe.sendmail(
recipients=frappe.db.get_value("User", doc.owner, "email") or doc.owner,
subject=subject,
message=message,
reference_doctype=doc.doctype,
reference_name=doc.name,
)

frappe/core/doctype/feedback/__init__.py → frappe/templates/includes/likes/__init__.py Ver fichero


frappe/templates/includes/feedback/feedback.html → frappe/templates/includes/likes/likes.html Ver fichero

@@ -1,20 +1,13 @@
<div class="feedback-item mr-3">
<div id="likes" class="feedback-item likes mr-3">
<span class="like-icon"></span>
<span class="like-count"></span>
</div>

<script type="text/javascript">
frappe.ready(() => {
let like = parseInt("{{ user_feedback.like or 0 }}");
let like = parseInt("{{ like or 0 }}");
let like_count = parseInt("{{ like_count or 0 }}");

let update_like = function() {
like = !like;
like ? like_count++ : like_count--;
toggle_like_icon(like);
$('.like-count').text(like_count);
}

let toggle_like_icon = function(active) {
active ? $('.like-icon').addClass('gray') : $('.like-icon').removeClass('gray');
}
@@ -26,16 +19,21 @@

$('.like-icon').click(() => {
update_like();
update_feedback();
})

let update_feedback = function() {
let update_like = function() {
like = !like;
like ? like_count++ : like_count--;
toggle_like_icon(like);
$('.like-count').text(like_count);

return frappe.call({
method: "frappe.templates.includes.feedback.feedback.give_feedback",
method: "frappe.templates.includes.likes.likes.like",
args: {
reference_doctype: "{{ reference_doctype or doctype }}",
reference_name: "{{ reference_name or name }}",
like
like,
route: "{{ pathname }}",
}
});
}

+ 77
- 0
frappe/templates/includes/likes/likes.py Ver fichero

@@ -0,0 +1,77 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: MIT. See LICENSE

import frappe
from frappe import _
from frappe.rate_limiter import rate_limit
from frappe.website.doctype.blog_settings.blog_settings import get_like_limit
from frappe.website.utils import clear_cache


@frappe.whitelist(allow_guest=True)
@rate_limit(key="reference_name", limit=get_like_limit, seconds=60 * 60)
def like(reference_doctype, reference_name, like, route=""):
like = frappe.parse_json(like)
ref_doc = frappe.get_doc(reference_doctype, reference_name)
if ref_doc.disable_likes == 1:
return

if like:
liked = add_like(reference_doctype, reference_name)
else:
liked = delete_like(reference_doctype, reference_name)

# since likes are embedded in the page, clear the web cache
if route:
clear_cache(route)

if like and ref_doc.enable_email_notification:
subject = _("Like on {0}: {1}").format(reference_doctype, reference_name)
content = _("You have received a ❤️ like on your blog post")
message = f"<p>{content} <b>{reference_name}</b></p>"
message = message + "<p><a href='{}/{}#likes' style='font-size: 80%'>{}</a></p>".format(
frappe.utils.get_request_site_address(), ref_doc.route, _("View Blog Post")
)

# notify creator
frappe.sendmail(
recipients=frappe.db.get_value("User", ref_doc.owner, "email") or ref_doc.owner,
subject=subject,
message=message,
reference_doctype=ref_doc.doctype,
reference_name=ref_doc.name,
)

return liked


def add_like(reference_doctype, reference_name):
user = frappe.session.user

like = frappe.new_doc("Comment")
like.comment_type = "Like"
like.comment_email = user
like.reference_doctype = reference_doctype
like.reference_name = reference_name
like.content = "Liked by: " + user
if user == "Guest":
like.ip_address = frappe.local.request_ip
like.save(ignore_permissions=True)
return True


def delete_like(reference_doctype, reference_name):
user = frappe.session.user

filters = {
"comment_type": "Like",
"comment_email": user,
"reference_doctype": reference_doctype,
"reference_name": reference_name,
}

if user == "Guest":
filters["ip_address"] = frappe.local.request_ip

frappe.db.delete("Comment", filters)
return False

+ 1
- 1
frappe/templates/pages/integrations/razorpay_checkout.py Ver fichero

@@ -51,7 +51,7 @@ def get_context(context):


def get_api_key():
api_key = frappe.db.get_value("Razorpay Settings", None, "api_key")
api_key = frappe.db.get_single_value("Razorpay Settings", "api_key")
if cint(frappe.form_dict.get("use_sandbox")):
api_key = frappe.conf.sandbox_api_key



+ 27
- 0
frappe/tests/test_naming.py Ver fichero

@@ -9,6 +9,7 @@ from frappe.model.naming import (
append_number_if_name_exists,
determine_consecutive_week_number,
getseries,
parse_naming_series,
revert_series_if_last,
)
from frappe.tests.utils import FrappeTestCase
@@ -342,6 +343,32 @@ class TestNaming(FrappeTestCase):
name.startswith("KOOH-on_update"), f"incorrect name generated {name}, missing field value"
)

def test_naming_with_empty_part(self):
# check naming with empty part (duplicate dots)

webhook = frappe.new_doc("Webhook")
webhook.webhook_docevent = "on_update"

series = "KOOH-..{webhook_docevent}.-.####"

name = parse_naming_series(series, doc=webhook)
self.assertTrue(
name.startswith("KOOH-on_update"), f"incorrect name generated {name}, missing field value"
)

def test_naming_with_unsupported_part(self):
# check naming with empty part (duplicate dots)

webhook = frappe.new_doc("Webhook")
webhook.webhook_docevent = {"dict": "not supported"}

series = "KOOH-..{webhook_docevent}.-.####"

name = parse_naming_series(series, doc=webhook)
self.assertTrue(
name.startswith("KOOH-"), f"incorrect name generated {name}, missing field value"
)


def make_invalid_todo():
frappe.get_doc({"doctype": "ToDo", "description": "Test"}).insert(set_name="ToDo")

+ 138
- 153
frappe/translations/ru.csv Ver fichero

@@ -107,7 +107,7 @@ Hourly,Почасовой,
Hub Sync ID,Идентификатор синхронизации концентратора,
IP Address,IP адрес,
Image,Изображение,
Image View,Просмотр изображения,
Image View,Просмотр изображений,
Import Data,Импорт данных,
Import Log,Лог импорта,
Inactive,Неактивный,
@@ -246,7 +246,7 @@ Start Import,Начать импорт,
State,Состояние,
Stopped,Приостановлено,
Subject,Тема,
Submit,Провести,
Submit,Подписать,
Successful,Успешно,
Summary,Резюме,
Sunday,Воскресенье,
@@ -445,7 +445,7 @@ Append To can be one of {0},Добавить к может быть одним
Append To is mandatory for incoming mails,Добавить к является обязательным для входящих сообщений,
"Append as communication against this DocType (must have fields, ""Status"", ""Subject"")","Добавить как коммуникацию для этого DocType (должен иметь поля, ""Статус"", ""Тема"")",
Applicable Document Types,Применимые типы документов,
Apply,Подать заявление,
Apply,Применить,
Apply Strict User Permissions,Применение строгих пользовательских разрешений,
Apply To All Document Types,Применить ко всем типам документов,
Apply this rule if the User is the Owner,"Применить это правило, если пользователь является владелец",
@@ -679,8 +679,8 @@ Client Information,Информация о клиенте,
Client Script,Скрипт клиента,
Client URLs,URL-адреса клиентов,
Client side script extensions in Javascript,Расширения клиентский сценарий в Javascript,
Collapsible,Складной,
Collapsible Depends On,Складные Зависит от,
Collapsible,Сворачиваемый,
Collapsible Depends On,Сворачиваемый - зависит от,
Column,Колонка,
Column <b>{0}</b> already exist.,Столбец <b>{0}</b> уже существует.,
Column Break,Разрыв столбца,
@@ -706,7 +706,8 @@ Compiled Successfully,Успешно скомпилировано,
Complete By,Завершить до,
Complete Registration,Полная регистрация,
Complete Setup,Завершение установки,
Completed By,Завершено,
Completed By,Завершил(а),
Completed On,Завершено,
Compose Email,Написать письмо,
Condition Detail,Детализация условий,
Conditions,Условия,
@@ -755,8 +756,6 @@ Created Custom Field {0} in {1},Дата создания настраиваем
Created On,Дата создания,
Criticism,Критика,
Criticize,Критиковать,
Ctrl + Down,Ctrl + Down,
Ctrl + Up,Ctrl + Up,
Ctrl+Enter to add comment,"Ctrl+Enter, чтобы добавить комментарий",
Currency Name,Название валюты,
Currency Precision,Точность валюты,
@@ -879,7 +878,7 @@ Disable SMTP server authentication,Отключить аутентификаци
Disable Sidebar Stats,Отключить статистику боковой панели,
Disable Signup,Отключение Регистрация,
Disable Standard Email Footer,Отключить стандартный нижний колонтитул электронной почты,
Discard,Отбросить,
Discard,Отменить,
Display,Показать,
Display Depends On,Показание зависит от,
Do not allow user to change after set the first time,Не позволяйте пользователю изменять после установить в первый раз,
@@ -1120,11 +1119,11 @@ First Transaction,Первая сделка,
First data column must be blank.,Первая колонка данных должна быть пустой.,
First set the name and save the record.,Сначала задайте имя и сохраните запись.,
Flag,Флаг,
Float,Сплавы,
Float Precision,Float Precision,
Fold,Сложить,
Fold can not be at the end of the form,Fold не может быть в конце виде,
Fold must come before a Section Break,Сложите должны прийти до перерыва раздел,
Float,Дробное,
Float Precision,Плавающая точность,
Fold,Сворачиваемое,
Fold can not be at the end of the form,Сворачиваемое поле не может быть в конце формы,
Fold must come before a Section Break,Сворачиваемое должно идти до разрыва раздел,
Folder,Папка,
Folder name should not include '/' (slash),Имя папки не должно включать «/» (косая черта),
Folder {0} is not empty,Папка {0} не пуста,
@@ -1240,15 +1239,12 @@ Home Settings,Домашние настройки,
Home/Test Folder 1,Главная/Тестовая Папка 1,
Home/Test Folder 1/Test Folder 3,Главная/Тестовая Папка 1/Тестовая Папка 3,
Home/Test Folder 2,Главная/Тестовая Папка 2,
Host,Host,
Hostname,Hostname,
"How should this currency be formatted? If not set, will use system defaults","Как следует отображать числа в этой валюте? Если не указано, то будут использоваться системные значения",
I found these: ,Я нашел следующее:,
I found these: ,Я нашел это: ,
ID,ID,
ID (name) of the entity whose property is to be set,"ID (имя) лица, имущество которого должно быть установлено",
Icon will appear on the button,Иконка появится на кнопке,
Identity Details,Сведения о личности,
Idx,Idx,
"If Apply Strict User Permission is checked and User Permission is defined for a DocType for a User, then all the documents where value of the link is blank, will not be shown to that User","Если флажок Apply Strict User Permission установлен, а для пользователя DocType для пользователя задано разрешение пользователя, тогда все документы, где значение ссылки пустым, не будут показаны этому пользователю",
If Checked workflow status will not override status in list view,"Если установлен флажок, статус процесса не будет отменять статус в журнале",
If Owner,Если владелец,
@@ -1303,7 +1299,7 @@ In Filter,В фильтрe,
In Global Search,В глобальном поиске,
In Grid View,В табличном виде,
In Hours,В час,
In List View,В виде списка,
In List View,Отображать в списке,
In Preview,В предварительном просмотре,
In Reply To,В ответ на,
In Standard Filter,В стандартный фильтр,
@@ -1322,7 +1318,7 @@ Index,Индекс,
Indicator,Индикатор,
Info,Информация,
Info:,Информация:,
Initial Sync Count,Первоначальная синхронизация Count,
Initial Sync Count,Первоначальная синхронизация,
InnoDB,InnoDB,
Insert Above,Вставить сверху,
Insert After,Вставить после,
@@ -1333,7 +1329,7 @@ Insert Column Before {0},Вставить столбец до {0},
Insert Style,Вставьте стиль,
Insert new records,Вставить новые записи,
Instructions Emailed,Инструкции отправлены по электронной почте,
Insufficient Permission for {0},Недостаточное разрешение для {0},
Insufficient Permission for {0},Недостаточно прав для {0},
Int,Интервал,
Integration Request,Интеграция заявки,
Integration Request Service,Интеграция заявки на обслуживание,
@@ -1374,33 +1370,30 @@ Invalid recipient address,Неверный адрес получателя,
Invalid {0} condition,Недопустимое условие {0},
Inverse,Обратный,
Is,Является,
Is Attachments Folder,Является папкой вложений,
Is Child Table,Является дочерней таблицей,
Is Attachments Folder,Это папка для вложений,
Is Child Table,Это дочерняя таблицей,
Is Custom Field,Это нестандартное поле,
Is First Startup,Первый запуск,
Is Folder,Папка,
Is Folder,Это папка,
Is Global,Является глобальным,
Is Globally Pinned,Глобально закреплено,
Is Home Folder,Является корневой папкой,
Is Mandatory Field,Является обязательным полем,
Is Pinned,Прикреплено,
Is Primary Contact,Основной контакт,
Is Primary Contact,Это основной контакт,
Is Private,Является приватным,
Is Published Field,Есть Опубликовано поле,
Is Published Field must be a valid fieldname,Опубликовано Поле должно быть действительным имя_полем,
Is Published Field,Это опубликованое поле,
Is Published Field must be a valid fieldname,Опубликованое роле должно быть допустимым именем поля,
Is Single,Единственный,
Is Spam,Спам,
Is Standard,Стандартный отчёт,
Is Spam,Это спам,
Is Standard,Это стандартный отчёт,
Is Submittable,Подлежит исполнению,
Is Table,Является таблицей,
Is Your Company Address,Является адресом вашей компании,
It is risky to delete this file: {0}. Please contact your System Manager.,"Рискованно удалять этот файл: {0}. Пожалуйста, обратитесь к менеджеру системы.",
Item cannot be added to its own descendents,Продукт не может быть добавлен к своим подпродуктам,
JS,JS,
JSON,JSON,
JavaScript Format: frappe.query_reports['REPORTNAME'] = {},Формат JavaScript: frappe.query_reports ['REPORTNAME'] = {},
Javascript to append to the head section of the page.,Javascript для добавления к головной части страницы.,
Jinja,Jinja,
John Doe,Джон Доу,
Kanban,Канбан,
Kanban Board Column,Колонка канбан-доски,
@@ -1480,7 +1473,7 @@ List,Список,
List Filter,Фильтр списка,
List View Setting,Настройка просмотра списка,
List a document type,Перечислите тип документа,
"List as [{""label"": _(""Jobs""), ""route"":""jobs""}]","Список как [{""Ярлык"": _(""Работы""), ""маршруты"":""работы""}]",
"List as [{""label"": _(""Jobs""), ""route"":""jobs""}]","Список как [{""Метка"": _(""Работы""), ""маршруты"":""работы""}]",
List of backups available for download,"Список резервных копий, доступных для загрузки",
List of patches executed,Список выполненных патчей,
List of themes for Website.,Список тем для сайта.,
@@ -1513,7 +1506,7 @@ Long Text,Длинный текст,
Looks like something is wrong with this site's Paypal configuration.,"Похоже, что что-то не так с конфигурацией Paypal этого сайта.",
Looks like something is wrong with this site's payment gateway configuration. No payment has been made.,"Похоже, что-то не так с конфигурацией платежного шлюза этого сайта. Платеж не был выполнен.",
"Looks like something went wrong during the transaction. Since we haven't confirmed the payment, Paypal will automatically refund you this amount. If it doesn't, please send us an email and mention the Correlation ID: {0}.","Похоже, что-то пошло не так во время транзакции. Поскольку мы не подтвердили платеж, Paypal автоматически вернет вам эту сумму. Если это не так, отправьте нам электронное письмо и укажите идентификатор корреляции: {0}.",
Madam,Госпожа,
Madam,Мадам,
Main Section,Основной раздел,
"Make ""name"" searchable in Global Search","Индексировать ""name"" для глобального поиска",
Make use of longer keyboard patterns,Используйте более длинных моделей клавиатуры,
@@ -1540,7 +1533,7 @@ Max Value,Макс. значение,
Max width for type Currency is 100px in row {0},Макс. ширина для типа валюты 100px в строке {0},
Maximum Attachment Limit for this record reached.,Достигнут предел вложений для этой записи.,
Maximum {0} rows allowed,Макс. {0} строк разрешено,
"Meaning of Submit, Cancel, Amend","Значение Провести, Отменить, Изменить",
"Meaning of Submit, Cancel, Amend","Значение Подписать, Отменить, Изменить",
Mention transaction completion page URL,URL-ссылка на страницу-упоминание о завершении транзакции,
Mentions,Упоминания,
Menu,Меню,
@@ -1606,14 +1599,14 @@ New Chat,Новый чат,
New Comment on {0}: {1},Новый комментарий к {0}: {1},
New Connection,Новое соединение,
New Custom Print Format,Новый пользовательский печатный бланк,
New Email,Новая электронная почта,
New Email,Новое письмо,
New Email Account,Новый аккаунт электронной почты,
New Event,Новое событие,
New Folder,Новая папка,
New Kanban Board,Новая панель канбан,
New Message from Website Contact Page,Новое сообщение с формы обратной связи на сайте,
New Name,Новое имя,
New Newsletter,Новый бюллетень,
New Newsletter,Новая новость,
New Password,Новый пароль,
New Password Required.,Требуется новый пароль.,
New Print Format Name,Название нового печатного бланка,
@@ -1672,8 +1665,8 @@ No template found at path: {0},Нет шаблона по адресу: {0},
No {0} found,{0} не найдено,
No {0} mail,Нет {0} почта,
No {0} permission,Нет {0} разрешение,
None: End of Workflow,Ни один: Конец потока,
Not Allowed: Disabled User,Не разрешено: отключен пользователь,
None: End of Workflow,Нет: конец рабочего процесса,
Not Allowed: Disabled User,Не разрешено: пользователь отключен,
Not Ancestors Of,Не предки,
Not Descendants Of,Не потомки,
Not Equals,Не равно,
@@ -1688,7 +1681,7 @@ Not a valid Comma Separated Value (CSV File),"Не является допуст
Not a valid User Image.,Недействительный изображение пользователя.,
Not a valid Workflow Action,Недоступное действие рабочего-процесса,
Not a valid user,Не является действительным пользователем,
Not a zip file,Не zip файл,
Not a zip file,Не является zip файлом,
Not allowed for {0}: {1},Не разрешено для {0}: {1},
Not allowed for {0}: {1} in Row {2}. Restricted field: {3},Недопустимо для {0}: {1} в строке {2}. Запрещенное поле: {3},
Not allowed for {0}: {1}. Restricted field: {2},Не допускается для {0}: {1}. Запрещенное поле: {2},
@@ -1732,11 +1725,11 @@ OTP Secret has been reset. Re-registration will be required on next login.,OTP S
OTP secret can only be reset by the Administrator.,Секрет OTP может быть сброшен администратором.,
Office,Офис,
Office 365,Офис 365,
Old Password,Старый Пароль,
Old Password Required.,Требуется старый пароль.,
Old Password,Старый пароль,
Old Password Required.,Старый пароль обязателен.,
Older backups will be automatically deleted,Более старые резервные копии будут автоматически удалены,
"On {0}, {1} wrote:","На {0}, {1} писал:",
"Once submitted, submittable documents cannot be changed. They can only be Cancelled and Amended.",После отправки поданные документы не могут быть изменены. Они могут быть только отменены и исправлены.,
"Once submitted, submittable documents cannot be changed. They can only be Cancelled and Amended.",После отправки подписанные документы не могут быть изменены. Они могут быть только отменены и исправлены.,
"Once you have set this, the users will only be able access documents (eg. Blog Post) where the link exists (eg. Blogger).","После такой установки, пользователи получат доступ только к документам (например, сообщениям в блоге), связанным с этими разрешениями пользователя (например, блоггера).",
One Last Step,Последний шаг,
One Time Password (OTP) Registration Code from {},Одноразовый пароль (OTP) Регистрационный код от {},
@@ -1760,7 +1753,7 @@ Open a dialog with mandatory fields to create a new record quickly,"Открой
Open a module or tool,Открыть модуль или инструмент,
Open your authentication app on your mobile phone.,Откройте приложение для проверки подлинности на своем мобильном телефоне.,
Open {0},Открыть {0},
Opened,Открыт,
Opened,Открыть,
Operator must be one of {0},Оператор должен быть одним из {0},
Option 1,Опция 1,
Option 2,Опция 2,
@@ -1778,9 +1771,7 @@ Org History Heading,Org История Заголовок,
Orientation,Ориентация,
Original Value,Первоначальная стоимость,
Outgoing email account not correct,Исходящая учетная запись электронной почты не верна,
Outlook.com,Outlook.com,
Output,Вывод,
PDF,PDF,
PDF Page Size,Размер PDF страницы,
PDF Settings,Настройки PDF,
PDF generation failed,Не удалось сгенерировать PDF-файл,
@@ -1790,17 +1781,17 @@ Page HTML,Страница HTML,
Page Length,Длина страницы,
Page Name,Имя страницы,
Page Settings,Настройки страницы,
Page has expired!,Страница просрочена!,
Page has expired!,Срок действия страницы истек!,
Page not found,Страница не найдена,
Page to show on the website\n,Страница для показа на сайте,
Pages in Desk (place holders),Страницы-заглушки,
Parent,Родитель,
Parent Error Snapshot,Родитель снимка ошибки,
Parent Label,Родительская метка,
Parent Table,Родитель Таблица,
Parent Table,Родительская таблица,
Parent is required to get child table data,Родитель обязан получать данные дочерней таблицы,
Parent is the name of the document to which the data will get added to.,"Родитель - это имя документа, к которому будут добавлены данные.",
Partial Success,Частичный успех,
Partial Success,Выполнено не полностью,
Partially Successful,Частично успешный,
Participants,Участники,
Passive,Пассивный,
@@ -1903,14 +1894,14 @@ Please specify which date field must be checked,"Просьба уточнить
Please specify which value field must be checked,"Просьба уточнить, какие значения поля должны быть проверены",
Please try again,"Пожалуйста, попробуйте еще раз",
Please verify your Email Address,"Пожалуйста, подтвердите свой адрес электронной почты",
Point Allocation Periodicity,Периодичность распределения точек,
Point Allocation Periodicity,Периодичность распределения баллов,
Points,Баллы,
Points Given,Баллы засчитаны,
Port,Порт,
Portal Menu,Меню портала,
Portal Menu Item,Портал Пункт меню,
Portal Menu Item,Пункт меню портала,
Post,Опубликовать,
Post Comment,Оставьте комментарий,
Post Comment,Оставить комментарий,
Postal,Почтовый,
Postal Code,Почтовый индекс,
Postprocess Method,Метод постпроцесса,
@@ -1966,15 +1957,6 @@ Provider Name,Имя поставщика,
Public Key,Открытый ключ,
Publishable Key,Ключ для публикации,
Published On,Опубликовано на,
Pull,Тянуть,
Pull Failed,Не удалось выполнить Pull,
Pull Insert,Вставить вкладыш,
Pull Update,Pull Update,
Push,От себя,
Push Delete,Нажмите Удалить,
Push Failed,Ошибка отправки,
Push Insert,Push Insert,
Push Update,Push Update,
Python Module,Модуль Python,
Pyver,Pyver,
QR Code,QR код,
@@ -1986,7 +1968,7 @@ Query,Запрос,
Query Report,Отчёт-выборка,
Query must be a SELECT,Запрос должен быть ВЫБОР,
Queue should be one of {0},Очередь должна быть одной из {0},
Queued for backup. It may take a few minutes to an hour.,Queued для резервного копирования. Это может занять несколько минут до часа.,
Queued for backup. It may take a few minutes to an hour.,В очереди для резервного копирования. Это может занять от несколько минут до часа.,
Queued for backup. You will receive an email with the download link,Очередь для резервного копирования. Вы получите электронное письмо с ссылкой для загрузки,
Quick Help for Setting Permissions,Быстрая помощь при настройки прав доступа,
Rating: ,Рейтинг: ,
@@ -2091,8 +2073,8 @@ Retake,пересдавать,
Retry,Повторить,
Return to the Verification screen and enter the code displayed by your authentication app,"Вернитесь на экран проверки и введите код, отображаемый приложением для аутентификации.",
Reverse Icon Color,Обратный цвет значка,
Revert,Вернуть,
Revert Of,Вернуть из,
Revert,Возврат,
Revert Of,Возвращенно из,
Reverted,Отменено,
Review Level,Уровень обзора,
Review Levels,Уровни обзора,
@@ -2101,9 +2083,8 @@ Reviews,Отзывы,
Revoke,Аннулировать,
Revoked,Аннулировано,
Rich Text,Форматированный текст,
Robots.txt,Robots.txt,
Role Name,Имя роли,
Role Permission for Page and Report,Роль Разрешение на страницу и отчет,
Role Name,Название роли,
Role Permission for Page and Report,Разрешение роли для страницы и отчета,
Role Permissions,Разрешения роли,
Role Profile,Профиль ролей,
Role and Level,Роль и уровень,
@@ -2198,7 +2179,7 @@ Select Print Format,Выберите бланк для печати,
Select Print Format to Edit,Выберите печатный бланк для редактирования,
Select Role,Выберите роль,
Select Table Columns for {0},Выберите столбцы таблицы для {0},
Select Your Region,Выберите регион,
Select Your Region,Выберите ваш регион,
Select a Brand Image first.,Выберите бренд изображение в первую очередь.,
Select a DocType to make a new format,"Выберите DOCTYPE, чтобы сделать новый бланк",
Select a chat to start messaging.,"Выберите чат, чтобы начать обмен сообщениями.",
@@ -2234,7 +2215,6 @@ Send only if there is any data,"Отправить только если ест
Send unsubscribe message in email,Отправить сообщение об отказе от подписки на электронную почту,
Sender,Отправитель,
Sender Email,Электронная почта отправителя,
Sendgrid,Sendgrid,
Sent Read Receipt,Отправлять уведомление о прочтении,
Sent or Received,Отправлено или получено,
Sent/Received Email,Отправлено/Получено письмо,
@@ -2279,8 +2259,8 @@ Setup Reports to be emailed at regular intervals,Настройка регуля
Share,Поделиться,
Share URL,Поделиться URL,
Share With,Поделиться с,
Share this document with,Поделитесь этот документ с,
Share {0} with,Поделиться {0},
Share this document with,Поделиться этим документом с,
Share {0} with,Поделиться {0} с,
Shared,Общий,
Shared With,Совместно с,
Shared with everyone,Общий для всех,
@@ -2325,8 +2305,6 @@ Single Post (article).,Один пост(статья).,
Single Types have only one record no tables associated. Values are stored in tabSingles,"Холост Типы нет только одна запись не таблицы, связанные. Значения сохраняются в tabSingles",
Skip Authorization,Пропустить авторизацию,
Skip rows with errors,Пропустить строки с ошибками,
Skype,Skype,
Slack,Slack,
Slack Channel,Slack канал,
Slack Webhook Error,Slack Webhook ошибка,
Slack Webhook URL,Неверный URL веб-хостинга,
@@ -2350,14 +2328,13 @@ Something went wrong while generating dropbox access token. Please check error l
Sorry! I could not find what you were looking for.,"Извините! Я не мог найти то, что вы ищете.",
Sorry! Sharing with Website User is prohibited.,Извините! Поделиться с сайта Пользователю запрещается.,
Sorry! User should have complete access to their own record.,Извините! Пользователь должен иметь полный доступ к своей записи.,
Sorry! You are not permitted to view this page.,Извините! Вам не разрешается для просмотра этой страницы.,
Sorry! You are not permitted to view this page.,Извините! У вас нет разрешений для просмотра этой страницы.,
"Sorry, you're not authorized.","Извините, вы не авторизованы.",
Sort Field,Сортировать поле,
Sort Order,Порядок сортировки,
Sort field {0} must be a valid fieldname,Сортировка поля {0} должен быть действительным имя_поля,
Source Text,Исходный текст,
Spam,Спам,
SparkPost,SparkPost,
Special Characters are not allowed,Спецсимволы не допустимы,
"Standard DocType cannot have default print format, use Customize Form","Стандартный DocType не может иметь формат печати по умолчанию, используйте Настроить форму",
Standard Print Format cannot be updated,Стандартный печатный бланк не может быть обновлен,
@@ -2371,12 +2348,11 @@ Start Date Field,Поле начальной даты,
Start a conversation.,Начните разговор.,
Start entering data below this line,Начните вводить данные ниже этой линии,
Start new Format,Начать новую Формат,
StartTLS,StartTLS,
Started,Начал,
Starting Frappe ...,Запуск Frappé ...,
Starts on,Начало,
States,Статусы,
"States for workflow (e.g. Draft, Approved, Cancelled).","Статусы бизнес-процесса (например: черновик, утверждён, отменён).",
States,Состояния,
"States for workflow (e.g. Draft, Approved, Cancelled).","Состояния рабочего-процесса (например: черновик, утверждён, отменён).",
Static Parameters,Статические параметры,
Stats based on last month's performance (from {0} to {1}),Статистика на основе результатов прошлого месяца (от {0} до {1}),
Stats based on last week's performance (from {0} to {1}),Статистика на основе результатов прошлой недели (от {0} до {1}),
@@ -2396,7 +2372,7 @@ Subdomain,Субдомен,
Subject Field,Поле темы,
Submit after importing,Отправить после импорта,
Submit an Issue,Отправить вопрос,
Submit this document to confirm,Провести этот документ для подтверждения,
Submit this document to confirm,Подписать этот документ для подтверждения,
Submit {0} documents?,Отправить {0} документы?,
Submitting {0},Помещение {0},
Submitted Document cannot be converted back to draft. Transition row {0},Проведенный Документ не может быть преобразован обратно в проект. Переходная строка {0},
@@ -2437,8 +2413,6 @@ Team Members,Члены команды,
Team Members Heading,Члены команды Возглавлять,
Temporarily Disabled,Временно отключен,
Test Email Address,Проверить адрес электронной почты,
Test Runner,Тест Runner,
Test_Folder,Test_Folder,
Text,Текст,
Text Align,Выравнивание текста,
Text Color,Цвет текста,
@@ -2463,8 +2437,8 @@ The system provides many pre-defined roles. You can add new roles to set finer p
The user from this field will be rewarded points,Пользователь из этого поля будет вознагражден баллами,
Theme,Тема,
Theme URL,URL темы,
There can be only one Fold in a form,Там может быть только один Fold в виде,
There is an error in your Address Template {0},Существует ошибка в адресной Шаблон {0},
There can be only one Fold in a form,В форме может быть только один Fold,
There is an error in your Address Template {0},Ошибка в вашем шаблоне адреса {0},
There is no data to be exported,Нет данных для экспорта,
There is some problem with the file url: {0},Существует некоторая проблема с файловой URL: {0},
There must be atleast one permission rule.,Там должно быть по крайней мере один правило разрешения.,
@@ -2502,7 +2476,7 @@ This is similar to a commonly used password.,Это похоже на обычн
This is the template file generated with only the rows having some error. You should use this file for correction and import.,"Это файл шаблона, сгенерированный только строками с некоторой ошибкой. Вы должны использовать этот файл для исправления и импорта.",
This link has already been activated for verification.,Эта ссылка уже была активирована для проверки.,
This link is invalid or expired. Please make sure you have pasted correctly.,"Эта ссылка является недействительным или истек. Пожалуйста, убедитесь, что вы вставили правильно.",
This may get printed on multiple pages,Это может быть напечатано на нескольких страницах,
This may get printed on multiple pages,Это будет напечатано на нескольких страницах,
This month,Этот месяц,
This query style is discontinued,Этот стиль запроса прекращен,
This report was generated on {0},Этот отчет был создан в {0},
@@ -2511,7 +2485,6 @@ This request has not yet been approved by the user.,Этот запрос еще
This role update User Permissions for a user,Эта роль обновляет разрешения пользователя для пользователя,
This will log out {0} from all other devices,Это выведет {0} из всех других устройств,
This will permanently remove your data.,Это навсегда удалит ваши данные.,
Throttled,Throttled,
Thumbnail URL,Миниатюра URL,
Time Interval,Интервал времени,
Time Series,Временные ряды,
@@ -2529,7 +2502,7 @@ Timeseries,Временные ряды,
Timestamp,Временная отметка,
Title Case,Название дела,
Title Field,Название поля,
Title Prefix,Название Приставка,
Title Prefix,Название приставки,
Title field must be a valid fieldname,Название поля должно быть допустимым имя_поля,
To Date Field,Поле даты,
To Do,Список дел,
@@ -2589,7 +2562,7 @@ Type:,Тип:,
UID,UID,
UIDNEXT,UIDNEXT,
UIDVALIDITY,UIDVALIDITY,
UNSEEN,НЕПРОЧИТАННО,
UNSEEN,НЕПРОЧИТАННЫЕ,
UPPER CASE,ВЕРХНИЙ РЕГИСТР,
"URIs for receiving authorization code once the user allows access, as well as failure responses. Typically a REST endpoint exposed by the Client App.\n<br>e.g. http://hostname//api/method/frappe.www.login.login_via_facebook","Идентификаторы URI для получения кода авторизации, как только пользователь разрешает доступ, а также ответы недостаточность. Как правило, конечная точка REST подвергается Клиентом App. <br> например, HTTP: //hostname//api/method/frappe.www.login.login_via_facebook",
URLs,URL-адрес,
@@ -2691,7 +2664,6 @@ Value for {0} cannot be a list,Значение {0} не может быть с
Value missing for,Нет значения для,
Value too big,Слишком большое значение,
Values Changed,Значения изменено,
Verdana,Verdana,
Verfication Code,Код проверки,
Verification Link,Ссылка для проверки,
Verification code has been sent to your registered email address.,Код подтверждения отправлен на ваш адрес электронной почты регистрации.,
@@ -2712,7 +2684,7 @@ View document,Просмотр документа,
View report in your browser,Просмотр отчета в вашем браузере,
View this in your browser,Просмотреть это в вашем браузере,
View {0},Просмотреть {0},
Viewed By,просмотрены,
Viewed By,Просмотрено,
Visit,Посетите нас по адресу,
Visitor,Посетитель,
We have received a request for deletion of {0} data associated with: {1},"Мы получили запрос на удаление {0} данных, связанных с: {1}",
@@ -2721,7 +2693,7 @@ Web Form,Веб форма,
Web Form Field,Поле веб формы,
Web Form Fields,Поля веб формы,
Web Page,Веб-страница,
Web Page Link Text,Web Текст Ссылка на страницу,
Web Page Link Text,Текст ссылки веб-страницы,
Web Site,Веб-сайт,
Web View,Web View,
Webhook,Webhook,
@@ -2765,9 +2737,7 @@ Workflow state represents the current state of a document.,Состояние р
Write,Написать,
Wrong fieldname <b>{0}</b> in add_fetch configuration of custom script,Неверное имя поля <b>{0}</b> в конфигурации add_fetch пользовательского скрипта,
X Axis Field,Поле оси X,
XLSX,XLSX,
Y Axis Fields,Поля оси Y,
Yahoo Mail,Yahoo Mail,
Yandex.Mail,Яндекс.Почта,
Yesterday,Вчера,
You are connected to internet.,Вы подключены к Интернету.,
@@ -2783,14 +2753,14 @@ You are not permitted to view the newsletter.,У Вас нет прав для
You are now following this document. You will receive daily updates via email. You can change this in User Settings.,Вы подписаны на обновления данного документа. Вы будете получать ежедневные обновления по электронной почте. Вы можете изменить это в настройках пользователя.,
You can add dynamic properties from the document by using Jinja templating.,Вы можете добавить динамические свойства из документа с помощью шаблонов Jinja.,
You can also copy-paste this ,Вы также можете скопировать и вставить это ,
"You can change Submitted documents by cancelling them and then, amending them.","Вы можете изменить Проведенные (Submitted) документы, отменив их, а затем изменив их.",
"You can change Submitted documents by cancelling them and then, amending them.","Вы можете изменить утвержденные документы, отменив их, а затем отредактировав.",
You can find things by asking 'find orange in customers',Можно искать что-либо написав «найти апельсин у клиентов»,
You can only upload upto 5000 records in one go. (may be less in some cases),"Вы можете загружать одновременно до 5000 записей. (Возможно меньше, в некоторых случаях)",
You can use Customize Form to set levels on fields.,Вы можете использовать Настройку формы (Customize Form) для установки уровней для полей.,
You can use wildcard %,Вы можете использовать подстановочные %,
You can't set 'Options' for field {0},Нельзя включить «Опции» для поля {0},
You can't set 'Translatable' for field {0},Вы не можете установить «Переводимый» для поля {0},
You cannot give review points to yourself,Вы не можете давать оценки себе,
You cannot give review points to yourself,Вы не можете не можете начислять себе баллы обзора,
You cannot unset 'Read Only' for field {0},Нельзя отменить «только чтение» для поля {0},
You do not have enough permissions to access this resource. Please contact your manager to get access.,"У вас нет достаточных прав для доступа к этому ресурсу. Пожалуйста, обратитесь к своему менеджеру, чтобы получить доступ.",
You do not have enough permissions to complete the action,У Вас нет достаточных прав для завершения действия,
@@ -2811,13 +2781,13 @@ You need to be in developer mode to edit a Standard Web Form,Вы должны
You need to be logged in and have System Manager Role to be able to access backups.,"Вы должны войти в систему (и иметь роль менеджера системы), чтобы иметь доступ к резервным копиям.",
You need to be logged in to access this {0}.,"Вы должны войти, чтобы получить доступ к {0}.",
"You need to have ""Share"" permission","Вы должны иметь разрешение ""Поделиться""",
You need write permission to rename,"Вам нужно письменное разрешение, чтобы переименовать",
You need write permission to rename,"Вам нужно разрешение на запись, чтобы переименовать",
You selected Draft or Cancelled documents,Вы выбрали черновик или отмененные документы,
You unfollowed this document,Вы отписались от этого документа,
Your Country,Ваша страна,
Your Language,Ваш язык,
Your Name,Ваше имя,
Your account has been locked and will resume after {0} seconds,Ваша учетная запись заблокирована и возобновится после {0} секунд,
Your account has been locked and will resume after {0} seconds,Ваша учетная запись заблокирована и будет доступна через {0} секунд,
Your connection request to Google Calendar was successfully accepted,Ваш запрос на подключение к Календарю Google был успешно принят,
Your information has been submitted,Ваша информация была представлена,
Your login id is,Ваш ID для авторизации,
@@ -2830,28 +2800,26 @@ Your payment was successfully accepted,Ваш платёж был успешно
"Your session has expired, please login again to continue.","Ваша сессия истекла, пожалуйста, войдите снова, чтобы продолжить.",
Zero,Ноль,
Zero means send records updated at anytime,При нуле обновленные записи отправляются в любое время,
_doctype,_doctype,
_report,_report,
adjust,настроить,
after_insert,после_вставки,
align-center,выровнять-центр,
align-justify,выровнять-оправдать,
align-left,выровнять левый,
align-right,выровнять правый,
align-center,выровнять-по-центру,
align-justify,выровнять-по-ширине,
align-left,выровнять-по-левой-стороне,
align-right,выровнять-по-правой-стороне,
ap-northeast-1,ар-северо-восток-1,
ap-northeast-2,ар-северо-восток-2,
ap-northeast-3,ар-северо-восток-3,
ap-south-1,ар-юго-1,
ap-southeast-1,ар-юго-восток-1,
ap-southeast-2,ар-юго-восток-2,
arrow-down,Стрелка вниз,
arrow-left,стрелка налево,
arrow-right,стрелка направо,
arrow-up,Стрелка вверх,
arrow-down,стрелка-вниз,
arrow-left,стрелка-налево,
arrow-right,стрелка-направо,
arrow-up,стрелка-вверх,
asterisk,звёздочка,
backward,назад,
ban-circle,Запрет круга,
bell,Накладная,
ban-circle,бан-кружок,
bell,колокольчик,
bookmark,закладка,
briefcase,портфель,
bullhorn,рупор,
@@ -2909,11 +2877,10 @@ gave {0} points,дал {0} баллов,
gift,подарок,
glass,стекло,
globe,глобус,
hand-down,ручной вниз,
hand-left,ручной левый,
hand-right,ручной право,
hand-up,грабитель,
hdd,жесткий диск,
hand-down,рука-вниз,
hand-left,рука-влево,
hand-right,рука-вправо,
hand-up,рука-вверх,
headphones,наушники,
heart,сердце,
hub,хаб,
@@ -3011,7 +2978,7 @@ zoom-in,приблизить,
zoom-out,отдалить,
{0} Calendar,{0} Календарь,
{0} Chart,{0} Диаграмма,
{0} Dashboard,{0} Панель инструментов,
{0} Dashboard,{0} Показатели,
{0} List,{0} Список,
{0} Modules,{0} Модули,
{0} Report,{0} Отчет,
@@ -3028,7 +2995,7 @@ zoom-out,отдалить,
{0} appreciated {1},{0} признателен {1},
{0} appreciation point for {1} {2},{0} благодарность за {1} {2},
{0} appreciation points for {1} {2},{0} баллы за {1} {2},
{0} assigned {1}: {2},{0} назначено {1}: {2},
{0} assigned {1}: {2},{0} назначил(а) {1}: {2},
{0} cannot be set for Single types,{0} не может быть установлена для отдельных видов,
{0} comments,{0} комментариев,
{0} created successfully,{0} создано успешно,
@@ -3053,7 +3020,7 @@ zoom-out,отдалить,
{0} is not a valid Workflow State. Please update your Workflow and try again.,{0} не является допустимым состоянием рабочего процесса. Обновите свой рабочий процесс и повторите попытку.,
{0} is now default print format for {1} doctype,{0} — теперь формат печати по умолчанию для {1} doctype,
{0} is saved,{0} сохранено,
{0} items selected,{0} продуктов выбрано,
{0} items selected,{0} элементов выбрано,
{0} logged in,{0} авторизирован,
{0} logged out: {1},{0} вышел: {1},
{0} minutes ago,{0} минут назад,
@@ -3097,7 +3064,7 @@ zoom-out,отдалить,
{0}: Cannot set Assign Submit if not Submittable,"{0}: Не удается установить Назначить проведение, если не подлежит проведению",
{0}: Cannot set Cancel without Submit,{0}: Не удается установить Отмена без отправки,
{0}: Cannot set Import without Create,{0}: Не удается установить Импорт без Создать,
"{0}: Cannot set Submit, Cancel, Amend without Write","{0}: Не удается выполнить Провести, Отменить, Изменить без Записать",
"{0}: Cannot set Submit, Cancel, Amend without Write","{0}: Не удается выполнить Подписать, Отменить, Изменить без Записать",
{0}: Cannot set import as {1} is not importable,{0}: Не удается установить импорт как {1} не является ввозу,
{0}: No basic permissions set,{0}: Не установлен базовый набор разрешений,
"{0}: Only one rule allowed with the same Role, Level and {1}","{0}: только одно правило допускается для той же роли, уровня и {1}",
@@ -3146,7 +3113,7 @@ About {0} seconds remaining,Осталось {0} секунд,
Access Log,Журнал доступа,
Access not allowed from this IP Address,Доступ с этого IP-адреса запрещен,
Action Type,Тип действия,
Activity Log by ,Активность Журнал по,
Activity Log by ,Журнал активности по ,
Add Fields,Добавить поля,
Administration,Администрирование,
After Cancel,После отмены,
@@ -3162,7 +3129,7 @@ Allow Auto Repeat,Разрешить автоматическое повторе
Allow Google Calendar Access,Разрешить доступ к календарю Google,
Allow Google Contacts Access,Разрешить доступ к контактам Google,
Allow Google Drive Access,Разрешить доступ Google Drive,
Allow Guest,Разрешить гость,
Allow Guest,Разрешить гостя,
Allow Guests to Upload Files,Разрешить гостям загружать файлы,
Also adding the status dependency field {0},Также добавляем поле зависимости статуса {0},
An error occurred while setting Session Defaults,Произошла ошибка при настройке параметров сеанса по умолчанию,
@@ -3216,8 +3183,8 @@ Click on the link below to approve the request,"Нажмите на ссылку
Click on the lock icon to toggle public/private,"Нажмите на значок замка, чтобы переключить публичный / приватный",
Click on {0} to generate Refresh Token.,"Нажмите {0}, чтобы сгенерировать токен обновления.",
Close Condition,Закрыть условие,
Column {0},Столбец {0},
Columns / Fields,Колонны / Поля,
Column {0},Колонка {0},
Columns / Fields,Колонки / Поля,
"Configure notifications for mentions, assignments, energy points and more.","Настройте уведомления для упоминаний, назначений, энергетических очков и многое другое.",
Contact Email,Эл.почта для связи,
Contact Numbers,Контактные номера,
@@ -3234,8 +3201,7 @@ Could not create razorpay order,Не удалось создать заказ н
Create Log,Создать журнал,
Create your first {0},Создайте свой первый {0},
Created {0} records successfully.,Создано {0} записей успешно.,
Cron,Cron,
Cron Format,Крон Формат,
Cron Format,Cron формат,
Daily Events should finish on the Same Day.,Ежедневные события должны заканчиваться в тот же день.,
Daily Long,Ежедневно,
Default Role on Creation,Роль по умолчанию при создании,
@@ -3257,10 +3223,10 @@ Document type is required to create a dashboard chart,Тип документа
Documentation Link,Документация Ссылка,
Don't Import,Не импортировать,
Don't Send Emails,Не отправлять электронные письма,
"Drag and drop files, ","Перетащите файлы,",
"Drag and drop files, ","Перетащите файлы, ",
Drop,Бросить,
Drop Here,Бросить тут,
Drop files here,Перетащите файлы сюда,
Drop files here,Поместите файлы сюда,
Dynamic Template,Динамический шаблон,
ERPNext Role,ERPNext роль,
Email / Notifications,Уведомления по электронной почте,
@@ -3407,7 +3373,7 @@ Last Update,Последнее обновление,
Last refreshed,Последнее обновление,
Link Document Type,Тип документа ссылки,
Link Fieldname,Имя поля ссылки,
Loading import file...,Загрузка файла импорта...,
Loading import file...,Загрузка импортируемого файла...,
Local Document Type,Локальный тип документа,
Log Data,Данные журнала,
Main Section (HTML),Основной раздел (HTML),
@@ -3415,7 +3381,7 @@ Main Section (Markdown),Основной раздел (Markdown),
"Maintains a Log of all inserts, updates and deletions on Event Producer site for documents that have consumers.","Ведение журнала всех вставок, обновлений и удалений на сайте Event Producer для документов, имеющих потребителей.",
Maintains a log of every event consumed along with the status of the sync and a Resync button in case sync fails.,"Ведение журнала всех использованных событий, а также состояния синхронизации и кнопки Resync в случае сбоя синхронизации.",
Make all attachments private,Сделайте все вложения приватными,
Mandatory Depends On,Обязательно зависит от,
Mandatory Depends On,Обязателен - зависит от,
Map Columns,Столбцы карты,
Map columns from {0} to fields in {1},Сопоставить столбцы из {0} с полями в {1},
Mapping column {0} to field {1},Отображение столбца {0} в поле {1},
@@ -3426,7 +3392,7 @@ Me,Мне,
Mention,Упоминание,
Modules,Модули,
Monthly Long,Ежемесячно долго,
Naming Series,Идентификация по Имени,
Naming Series,Именование серии,
Navigate Home,Навигация Домой,
Navigate list down,Переместиться вниз по списку,
Navigate list up,Навигация по списку вверх,
@@ -3483,7 +3449,7 @@ Press Alt Key to trigger additional shortcuts in Menu and Sidebar,"Нажмит
Print Settings...,Настройки печати...,
Producer Document Name,Название документа производителя,
Producer URL,URL производителя,
Property Depends On,Недвижимость зависит от,
Property Depends On,Свойства зависят от,
Pull from Google Calendar,Загрузить из календаря Google,
Pull from Google Contacts,Загрузить из контактов Google,
Pulled from Google Calendar,Загружено из календаря Google,
@@ -3493,7 +3459,7 @@ Push to Google Contacts,Нажмите на контакты Google,
Queue / Worker,Очередь / Рабочий,
RAW Information Log,Необработанный информационный журнал,
Raw Printing Settings...,Настройки необработанной печати...,
Read Only Depends On,Только чтение зависит от,
Read Only Depends On,Только для чтения - зависит от,
Recent Activity,Недавняя активность,
Reference document has been cancelled,Справочный документ был отменен,
Reload File,Перезагрузить файл,
@@ -3526,6 +3492,7 @@ Select Date Range,Выберите диапазон дат,
Select Field,Выберите поле,
Select Field...,Выберите поле...,
Select Filters,Выберите фильтры,
Edit Filters,Изменить фильтры,
Select Google Calendar to which event should be synced.,"Выберите календарь Google, к которому нужно синхронизировать событие.",
Select Google Contacts to which contact should be synced.,"Выберите Google Контакты, с которыми контакт должен быть синхронизирован.",
Select Group By...,Выбрать группу по...,
@@ -3646,7 +3613,7 @@ Workflow Status,Состояние рабочего процесса,
You are not allowed to export {} doctype,Вы не можете экспортировать {} doctype,
You can try changing the filters of your report.,Вы можете попробовать изменить фильтры вашего отчета.,
You do not have permissions to cancel all linked documents.,У вас нет прав для отмены всех связанных документов.,
You need to create these first: ,Вам нужно сначала создать это: ,
You need to create these first: ,Вам сначала нужно создать: ,
You need to enable JavaScript for your app to work.,Вам нужно включить JavaScript для вашего приложения для работы.,
You need to install pycups to use this feature!,"Вам нужно установить pycups, чтобы использовать эту функцию!",
Your Target,Ваша цель,
@@ -3708,7 +3675,7 @@ Currency,Валюта,
Customize,Настроить,
Daily,Ежедневно,
Date,Дата,
Dear,Уважаемый (ая),
Dear,Уважаемый(ая),
Default,По умолчанию,
Delete,Удалить,
Description,Описание,
@@ -3727,7 +3694,7 @@ Entity Type,Тип объекта,
Error,Ошибка,
Expired,Истек срок действия,
Export,Экспорт,
Export not allowed. You need {0} role to export.,Экспорт не допускается. Вам нужно {0} роль для экспорта.,
Export not allowed. You need {0} role to export.,Экспорт не допускается. Вам нужна роль {0} для экспорта.,
Fetching...,Получение...,
Field,Поле,
File Manager,Файловый менеджер,
@@ -3788,7 +3755,6 @@ Set,Задать,
Setup,Настройки,
Setup Wizard,Мастер установки,
Size,Размер,
Sr,Sr,
Start,Начать,
Start Time,Стартовое время,
Status,Статус,
@@ -3798,7 +3764,7 @@ Template,Шаблон,
Thursday,Четверг,
Title,Заголовок,
Total,Общая сумма,
Totals,Всего:,
Totals,Всего,
Tuesday,Вторник,
Type,Тип,
Update,Обновить,
@@ -3809,10 +3775,10 @@ Welcome to {0},Добро пожаловать в {0},
Year,Год,
Yearly,Ежегодно,
You,Вы,
You can also copy-paste this link in your browser,Ещё можно скопировать эту ссылку в браузер,
You can also copy-paste this link in your browser,Вы также можете скопировать и вставить эту ссылку в свой браузер,
and,и,
{0} Name,{0} Имя,
{0} is required,{0} требуется,
{0} is required,{0} является обязательным,
ALL,ВСЕ,
Attach File,Прикрепить файл,
Barcode,Штрих-код,
@@ -3887,7 +3853,6 @@ Hidden,Скрытый,
Javascript,Javascript,
Ldap settings,Настройки Ldap,
Mobile number,Мобильный номер,
Mx,Mx,
No,Нет,
Not found,Не обнаружена,
Notes:,Примечания:,
@@ -3994,7 +3959,7 @@ Desk Page,Рабочий стол,
Desk Shortcut,Сочетание клавиш,
Developer Mode Only,Только режим разработчика,
Disable User Customization,Отключить настройку пользователя,
For example: {} Open,Например: {} Open,
For example: {} Open,Например: {} Открыто,
Link Cards,Карты ссылок,
Link To,Ссылка к,
Onboarding,Вводный,
@@ -4026,6 +3991,7 @@ Select Language,Выбрать язык,
Confirm Translations,Подтвердить перевод,
Contributed Translations,Добавленные переводы,
Show Tags,Показать теги,
Hide Tags,Скрыть теги,
Do not have permission to access {0} bucket.,У вас нет разрешения на доступ к сегменту {0}.,
Allow document creation via Email,Разрешить создание документов по электронной почте,
Sender Field,Поле отправителя,
@@ -4218,12 +4184,12 @@ since last year,с прошлого года,
Show,Показать,
New Number Card,Карточка с новым номером,
Your Shortcuts,Ваши ярлыки,
You haven't added any Dashboard Charts or Number Cards yet.,Вы еще не добавили диаграммы или карточки с цифрами.,
Click On Customize to add your first widget,"Нажмите &quot;Настроить&quot;, чтобы добавить свой первый виджет.",
You haven't added any Dashboard Charts or Number Cards yet.,Вы еще не добавили диаграммы или карточки с показателями.,
Click On Customize to add your first widget,"Нажмите Настроить, чтобы добавить свой первый виджет.",
Are you sure you want to reset all customizations?,"Вы уверены, что хотите сбросить все настройки?",
"Couldn't save, please check the data you have entered","Не удалось сохранить, проверьте данные, которые вы ввели",
Validation Error,Ошибка проверки,
"You can only upload JPG, PNG, PDF, or Microsoft documents.","Вы можете загружать только документы в форматах JPG, PNG, PDF или Microsoft.",
"You can only upload JPG, PNG, PDF, or Microsoft documents.","Вы можете загружать только документы в форматах JPG, PNG, PDF или документы Microsoft.",
Reverting length to {0} for '{1}' in '{2}'. Setting the length as {3} will cause truncation of data.,Возврат длины к {0} для &#39;{1}&#39; в &#39;{2}&#39;. Установка длины как {3} вызовет усечение данных.,
'{0}' not allowed for type {1} in row {2},&#39;{0}&#39; не разрешено для типа {1} в строке {2},
Option {0} for field {1} is not a child table,Вариант {0} для поля {1} не является дочерней таблицей,
@@ -4437,7 +4403,7 @@ CTA,CTA,
CTA Label,Метка CTA,
CTA URL,CTA URL,
Default Portal Home,Главная страница портала по умолчанию,
"Example: ""/desk""",Пример: &quot;/ стол&quot;,
"Example: ""/desk""","Пример: ""/desk""",
Social Link Settings,Настройки социальных ссылок,
Social Link Type,Тип социальной ссылки,
facebook,facebook,
@@ -4543,11 +4509,11 @@ Too Many Requests,Слишком много запросов,
{} is not a valid date string.,{} не является допустимой строкой даты.,
Invalid Date,Недействительная дата,
Please select a valid date filter,"Пожалуйста, выберите действующий фильтр даты",
Value {0} must be in the valid duration format: d h m s,Значение {0} должно иметь допустимый формат продолжительности: dhms.,
Value {0} must be in the valid duration format: d h m s,Значение {0} должно иметь допустимый формат продолжительности: д ч м с,
Google Sheets URL is invalid or not publicly accessible.,URL-адрес Google Таблиц недействителен или не является общедоступным.,
"Google Sheets URL must end with ""gid={number}"". Copy and paste the URL from the browser address bar and try again.",URL-адрес Google Таблиц должен заканчиваться на &quot;gid = {number}&quot;. Скопируйте и вставьте URL-адрес из адресной строки браузера и повторите попытку.,
Incorrect URL,Неверный URL,
"""{0}"" is not a valid Google Sheets URL",&quot;{0}&quot; не является действительным URL-адресом Google Таблиц,
"""{0}"" is not a valid Google Sheets URL","""{0}"" не является действительным URL-адресом Google Таблиц",
Duplicate Name,Повторяющееся имя,
"Please check the value of ""Fetch From"" set for field {0}","Проверьте значение параметра &quot;Получить из&quot;, установленное для поля {0}.",
Wrong Fetch From value,Неверное значение Fetch From,
@@ -4567,7 +4533,7 @@ Hourly comment limit reached for: {0},Достигнут лимит почасо
Please add a valid comment.,"Пожалуйста, добавьте действительный комментарий.",
Document {0} Already Restored,Документ {0} уже восстановлен,
Restoring Deleted Document,Восстановление удаленного документа,
{function} of {fieldlabel},{функция} из {fieldlabel},
{function} of {fieldlabel},{function} из {fieldlabel},
Invalid template file for import,Неверный файл шаблона для импорта,
Invalid or corrupted content for import,Недействительный или поврежденный контент для импорта,
Value {0} must in {1} format,Значение {0} должно быть в формате {1},
@@ -4575,7 +4541,7 @@ Value {0} must in {1} format,Значение {0} должно быть в фо
Could not map column {0} to field {1},Не удалось сопоставить столбец {0} с полем {1},
Skipping Duplicate Column {0},Пропуск повторяющегося столбца {0},
The column {0} has {1} different date formats. Automatically setting {2} as the default format as it is the most common. Please change other values in this column to this format.,"Столбец {0} имеет {1} разные форматы даты. Автоматическая установка {2} в качестве формата по умолчанию, поскольку он является наиболее распространенным. Измените другие значения в этом столбце на этот формат.",
You have reached the hourly limit for generating password reset links. Please try again later.,"Вы достигли почасового лимита для создания ссылок для сброса пароля. Пожалуйста, попробуйте позже.",
You have reached the hourly limit for generating password reset links. Please try again later.,"Вы достигли лимита на создание ссылок для сброса пароля. Пожалуйста, попробуйте позже.",
Please hide the standard navbar items instead of deleting them,Скройте стандартные элементы навигационной панели вместо их удаления,
DocType's name should not start or end with whitespace,Имя DocType не должно начинаться или заканчиваться пробелом,
File name cannot have {0},Имя файла не может содержать {0},
@@ -4600,14 +4566,14 @@ Delivery Failed,Доставка не удалась,
Twilio WhatsApp Message Error,Ошибка сообщения Twilio WhatsApp,
A featured post must have a cover image,В избранном посте должна быть обложка.,
Load More,Показать больше,
Published on,Опубликован в,
Published on,Опубликован,
Enable developer mode to create a standard Web Template,"Включите режим разработчика, чтобы создать стандартный веб-шаблон",
Was this article helpful?,Эта статья была полезной?,
Thank you for your feedback!,Спасибо за ваш отзыв!,
New Mention on {0},Новое упоминание о {0},
Assignment Update on {0},Обновление задания на {0},
New Document Shared {0},Новый документ опубликован {0},
Energy Point Update on {0},Обновление Energy Point от {0},
Energy Point Update on {0},Обновление баллов активности от {0},
You cannot create a dashboard chart from single DocTypes,Вы не можете создать диаграмму панели мониторинга из одного типа документов,
Invalid json added in the custom options: {0},В настраиваемые параметры добавлен недопустимый json: {0},
Invalid JSON in card links for {0},Недействительный JSON в ссылках на карточки для {0},
@@ -4629,7 +4595,7 @@ Worflow States Don't Exist,Состояния Worflow не существуют,
Save Anyway,Все равно сохранить,
Energy Points:,Баллы активности:,
Review Points:,Баллы обзора:,
Rank:,Ранг:,
Rank:,Рейтинг:,
Monthly Rank:,Месячный рейтинг:,
Invalid expression set in filter {0} ({1}),Недопустимое выражение в фильтре {0} ({1}),
Invalid expression set in filter {0},В фильтре {0} задано недопустимое выражение,
@@ -4688,12 +4654,12 @@ Open URL in a New Tab,Открыть URL в новой вкладке,
Align Right,Выровнять по правому краю,
Loading Filters...,Загрузка фильтров...,
Count Customizations,Подсчет настроек,
For Example: {} Open,Например: {} Открыть,
For Example: {} Open,Например: {} Открыто,
Choose Existing Card or create New Card,Выберите существующую карту или создайте новую карту,
Number Cards,Числовые карты,
Function Based On,Функция на основе,
Add Filters,Добавить фильтры,
Skip,Пропускать,
Skip,Пропустить,
Dismiss,Отклонить,
Value cannot be negative for,Значение не может быть отрицательным для,
Value cannot be negative for {0}: {1},Значение не может быть отрицательным для {0}: {1},
@@ -4702,9 +4668,28 @@ Authentication failed while receiving emails from Email Account: {0}.,Ошибк
Message from server: {0},Сообщение с сервера: {0},
Documentation,Документация,
User Forum,Форум пользователей,
Report an issue,Сообщить об ошибке,
Report an Issue,Сообщить об ошибке,
About,О системе,
My Profile,Мой профиль,
My Settings,Мои настройки,
Toggle Full Width,Переключить ширину,
Toggle Theme,Переключить тему,
Modules,Модули,
You created this {0},Вы создали это {0},
{0} created this {1},{0} создал(а) это {1},
You edited this {0},Вы отредактировали это {0},
{0} edited this {1},{0} отредактировал(а) это {1},
You viewed this {0},Вы просмотрели это {0},
{0} viewed this {1},{0} просмотрел(а) это {1},
Apply Filters,Применить фильтры,
+ Add a Filter,+ Добавить фильтр,
Is Template,Является шаблоном,
Show Saved,Показать сохраненные,
Hide Saved,Скрыть сохраненные,
Add Tags,Добавить теги,
Page Size,Формат страницы,
Set all public,Сделать публичными,
Set all private,Сделать приватными,
Drag and drop files here or upload from,Перетащите файлы сюда или загрузите из,
My Device,Моё устройство,
Library,Библиотека,

+ 9
- 13
frappe/twofactor.py Ver fichero

@@ -43,10 +43,10 @@ def toggle_two_factor_auth(state, roles=None):

def two_factor_is_enabled(user=None):
"""Returns True if 2FA is enabled."""
enabled = int(frappe.db.get_value("System Settings", None, "enable_two_factor_auth") or 0)
enabled = int(frappe.db.get_single_value("System Settings", "enable_two_factor_auth") or 0)
if enabled:
bypass_two_factor_auth = int(
frappe.db.get_value("System Settings", None, "bypass_2fa_for_retricted_ip_users") or 0
frappe.db.get_single_value("System Settings", "bypass_2fa_for_retricted_ip_users") or 0
)
if bypass_two_factor_auth and user:
user_doc = frappe.get_doc("User", user)
@@ -145,7 +145,7 @@ def get_otpsecret_for_(user):


def get_verification_method():
return frappe.db.get_value("System Settings", None, "two_factor_method")
return frappe.db.get_single_value("System Settings", "two_factor_method")


def confirm_otp_token(login_manager, otp=None, tmp_id=None):
@@ -191,7 +191,7 @@ def confirm_otp_token(login_manager, otp=None, tmp_id=None):


def get_verification_obj(user, token, otp_secret):
otp_issuer = frappe.db.get_value("System Settings", "System Settings", "otp_issuer_name")
otp_issuer = frappe.db.get_single_value("System Settings", "otp_issuer_name")
verification_method = get_verification_method()
verification_obj = None
if verification_method == "SMS":
@@ -267,7 +267,7 @@ def process_2fa_for_email(user, token, otp_secret, otp_issuer, method="Email"):
def get_email_subject_for_2fa(kwargs_dict):
"""Get email subject for 2fa."""
subject_template = _("Login Verification Code from {}").format(
frappe.db.get_value("System Settings", "System Settings", "otp_issuer_name")
frappe.db.get_single_value("System Settings", "otp_issuer_name")
)
subject = frappe.render_template(subject_template, kwargs_dict)
return subject
@@ -287,7 +287,7 @@ def get_email_body_for_2fa(kwargs_dict):
def get_email_subject_for_qr_code(kwargs_dict):
"""Get QRCode email subject."""
subject_template = _("One Time Password (OTP) Registration Code from {}").format(
frappe.db.get_value("System Settings", "System Settings", "otp_issuer_name")
frappe.db.get_single_value("System Settings", "otp_issuer_name")
)
subject = frappe.render_template(subject_template, kwargs_dict)
return subject
@@ -307,9 +307,7 @@ def get_link_for_qrcode(user, totp_uri):
key = frappe.generate_hash(length=20)
key_user = f"{key}_user"
key_uri = f"{key}_uri"
lifespan = (
int(frappe.db.get_value("System Settings", "System Settings", "lifespan_qrcode_image")) or 240
)
lifespan = int(frappe.db.get_single_value("System Settings", "lifespan_qrcode_image")) or 240
frappe.cache().set_value(key_uri, totp_uri, expires_in_sec=lifespan)
frappe.cache().set_value(key_user, user, expires_in_sec=lifespan)
return get_url(f"/qrcode?k={key}")
@@ -465,9 +463,7 @@ def should_remove_barcode_image(barcode):
"""Check if it's time to delete barcode image from server."""
if isinstance(barcode, str):
barcode = frappe.get_doc("File", barcode)
lifespan = (
frappe.db.get_value("System Settings", "System Settings", "lifespan_qrcode_image") or 240
)
lifespan = frappe.db.get_single_value("System Settings", "lifespan_qrcode_image") or 240
if time_diff_in_seconds(get_datetime(), barcode.creation) > int(lifespan):
return True
return False
@@ -482,7 +478,7 @@ def reset_otp_secret(user):
if frappe.session.user != user:
frappe.only_for("System Manager", message=True)

otp_issuer = frappe.db.get_value("System Settings", "System Settings", "otp_issuer_name")
otp_issuer = frappe.db.get_single_value("System Settings", "otp_issuer_name")
user_email = frappe.db.get_value("User", user, "email")

clear_default(user + "_otplogin")


+ 1
- 1
frappe/utils/data.py Ver fichero

@@ -1545,7 +1545,7 @@ def get_url(uri: str | None = None, full_address: bool = False) -> str:
host_name = protocol + frappe.local.site

else:
host_name = frappe.db.get_value("Website Settings", "Website Settings", "subdomain")
host_name = frappe.db.get_single_value("Website Settings", "subdomain")

if not host_name:
host_name = "http://localhost"


+ 1
- 0
frappe/utils/safe_exec.py Ver fichero

@@ -152,6 +152,7 @@ def get_safe_globals():
enqueue=safe_enqueue,
sanitize_html=frappe.utils.sanitize_html,
log_error=frappe.log_error,
log=frappe.log,
db=NamespaceDict(
get_list=frappe.get_list,
get_all=frappe.get_all,


+ 9
- 9
frappe/website/doctype/blog_post/blog_post.json Ver fichero

@@ -19,7 +19,7 @@
"hide_cta",
"enable_email_notification",
"disable_comments",
"disable_feedback",
"disable_likes",
"section_break_5",
"blog_intro",
"content_type",
@@ -194,18 +194,18 @@
"label": "Meta Title",
"length": 60
},
{
"default": "0",
"fieldname": "disable_feedback",
"fieldtype": "Check",
"label": "Disable Feedback"
},
{
"default": "1",
"description": "Enable email notification for any comment or feedback on your Blog Post.",
"description": "Enable email notification for any comment or likes received on your Blog Post.",
"fieldname": "enable_email_notification",
"fieldtype": "Check",
"label": "Enable Email Notification"
},
{
"default": "0",
"fieldname": "disable_likes",
"fieldtype": "Check",
"label": "Disable Likes"
}
],
"has_web_view": 1,
@@ -214,7 +214,7 @@
"index_web_pages_for_search": 1,
"is_published_field": "published",
"links": [],
"modified": "2022-03-21 14:42:19.282612",
"modified": "2022-07-12 17:40:10.221000",
"modified_by": "Administrator",
"module": "Website",
"name": "Blog Post",


+ 25
- 27
frappe/website/doctype/blog_post/blog_post.py Ver fichero

@@ -116,7 +116,7 @@ class BlogPost(WebsiteGenerator):
context.metatags["image"] = self.meta_image or image or None

self.load_comments(context)
self.load_feedback(context)
self.load_likes(context)

context.category = frappe.db.get_value(
"Blog Category", context.doc.blog_category, ["title", "route"], as_dict=1
@@ -164,33 +164,27 @@ class BlogPost(WebsiteGenerator):
context.comment_list = get_comment_list(self.doctype, self.name)

if not context.comment_list:
context.comment_text = 0
context.comment_count = 0
else:
context.comment_text = len(context.comment_list)
context.comment_count = len(context.comment_list)

def load_feedback(self, context):
def load_likes(self, context):
user = frappe.session.user

feedback = frappe.get_all(
"Feedback",
fields=["like"],
filters=dict(
reference_doctype=self.doctype,
reference_name=self.name,
ip_address=frappe.local.request_ip,
owner=user,
),
)
filters = {
"comment_type": "Like",
"reference_doctype": self.doctype,
"reference_name": self.name,
}

like_count = 0
context.like_count = frappe.db.count("Comment", filters) or 0

if frappe.db.count("Feedback"):
like_count = frappe.db.count(
"Feedback", filters=dict(reference_doctype=self.doctype, reference_name=self.name, like=True)
)
filters["comment_email"] = user

context.user_feedback = feedback[0] if feedback else ""
context.like_count = like_count
if user == "Guest":
filters["ip_address"] = frappe.local.request_ip

context.like = frappe.db.count("Comment", filters) or 0

def set_read_time(self):
content = self.content or self.content_html or ""
@@ -279,12 +273,16 @@ def get_blog_list(
doctype, txt=None, filters=None, limit_start=0, limit_page_length=20, order_by=None
):
conditions = []
category = filters.blog_category or frappe.utils.escape_html(
frappe.local.form_dict.blog_category or frappe.local.form_dict.category
)
if filters:
if filters.blogger:
conditions.append("t1.blogger=%s" % frappe.db.escape(filters.blogger))
if filters and filters.get("blog_category"):
category = filters.get("blog_category")
else:
category = frappe.utils.escape_html(
frappe.local.form_dict.blog_category or frappe.local.form_dict.category
)

if filters and filters.get("blogger"):
conditions.append("t1.blogger=%s" % frappe.db.escape(filters.get("blogger")))

if category:
conditions.append("t1.blog_category=%s" % frappe.db.escape(category))



+ 16
- 3
frappe/website/doctype/blog_post/templates/blog_post.html Ver fichero

@@ -44,8 +44,8 @@
{%- endif -%}
<div class="blog-footer">
<div class="blog-feedback">
{% if not disable_feedback %}
{% include 'templates/includes/feedback/feedback.html' %}
{% if not disable_likes %}
{% include 'templates/includes/likes/likes.html' %}
{% endif %}
</div>
{% if social_links %}
@@ -73,6 +73,19 @@

</div>
<script>
frappe.ready(() => frappe.set_search_path("/blog"))
frappe.ready(() => {
frappe.set_search_path("/blog");

// scroll to comment or like section if url contain hash
if (window.location.hash) {
var hash = window.location.hash;

if ($(hash).length) {
$('html, body').animate({
scrollTop: $(hash).offset().top - 100
}, 900, 'swing');
}
}
})
</script>
{% endblock %}

+ 23
- 0
frappe/website/doctype/blog_post/test_blog_post.py Ver fichero

@@ -152,6 +152,29 @@ class TestBlogPost(FrappeTestCase):
frappe.delete_doc("Blog Post", blog.name)
frappe.delete_doc("Blog Category", blog.blog_category)

def test_like_dislike(self):
test_blog = make_test_blog()

frappe.db.delete("Comment", {"comment_type": "Like", "reference_doctype": "Blog Post"})

from frappe.templates.includes.likes.likes import like

frappe.form_dict.reference_doctype = "Blog Post"
frappe.form_dict.reference_name = test_blog.name
frappe.form_dict.like = True
frappe.local.request_ip = "127.0.0.1"

liked = like()
self.assertEqual(liked, True)

frappe.form_dict.like = False

disliked = like()
self.assertEqual(disliked, False)

frappe.db.delete("Comment", {"comment_type": "Like", "reference_doctype": "Blog Post"})
test_blog.delete()


def scrub(text):
return WebsiteGenerator.scrub(None, text)


+ 9
- 9
frappe/website/doctype/blog_settings/blog_settings.json Ver fichero

@@ -19,7 +19,7 @@
"cta_label",
"cta_url",
"section_break_12",
"feedback_limit",
"like_limit",
"column_break_14",
"comment_limit"
],
@@ -89,13 +89,6 @@
"fieldname": "section_break_12",
"fieldtype": "Section Break"
},
{
"default": "5",
"description": "Feedback limit per hour",
"fieldname": "feedback_limit",
"fieldtype": "Int",
"label": "Feedback limit"
},
{
"default": "5",
"description": "Comment limit per hour",
@@ -118,13 +111,20 @@
"fieldname": "browse_by_category",
"fieldtype": "Check",
"label": "Browse by category"
},
{
"default": "5",
"description": "Like limit per hour",
"fieldname": "like_limit",
"fieldtype": "Int",
"label": "Like limit"
}
],
"icon": "fa fa-cog",
"idx": 1,
"issingle": 1,
"links": [],
"modified": "2021-12-20 13:40:32.312459",
"modified": "2022-07-12 17:45:49.108398",
"modified_by": "Administrator",
"module": "Website",
"name": "Blog Settings",


+ 2
- 2
frappe/website/doctype/blog_settings/blog_settings.py Ver fichero

@@ -15,8 +15,8 @@ class BlogSettings(Document):
clear_cache("writers")


def get_feedback_limit():
return frappe.db.get_single_value("Blog Settings", "feedback_limit") or 5
def get_like_limit():
return frappe.db.get_single_value("Blog Settings", "like_limit") or 5


def get_comment_limit():


+ 1
- 1
frappe/website/doctype/web_page_view/web_page_view.py Ver fichero

@@ -49,4 +49,4 @@ def get_page_view_count(path):


def is_tracking_enabled():
return frappe.db.get_value("Website Settings", "Website Settings", "enable_view_tracking")
return frappe.db.get_single_value("Website Settings", "enable_view_tracking")

+ 1
- 1
frappe/website/doctype/website_settings/google_indexing.py Ver fichero

@@ -16,7 +16,7 @@ def authorize_access(reauthorize=False, code=None):
"""If no Authorization code get it from Google and then request for Refresh Token."""

oauth_code = (
frappe.db.get_value("Website Settings", "Website Settings", "indexing_authorization_code")
frappe.db.get_single_value("Website Settings", "indexing_authorization_code")
if not code
else code
)


+ 1
- 1
frappe/www/contact.py Ver fichero

@@ -51,7 +51,7 @@ def send_message(subject="Website Query", message="", sender=""):
return

# send email
forward_to_email = frappe.db.get_value("Contact Us Settings", None, "forward_to_email")
forward_to_email = frappe.db.get_single_value("Contact Us Settings", "forward_to_email")
if forward_to_email:
frappe.sendmail(recipients=forward_to_email, sender=sender, content=message, subject=subject)



+ 1
- 1
package.json Ver fichero

@@ -32,7 +32,7 @@
"driver.js": "^0.9.8",
"editorjs-undo": "0.1.6",
"fast-deep-equal": "^2.0.1",
"frappe-charts": "^2.0.0-rc13",
"frappe-charts": "2.0.0-rc22",
"frappe-datatable": "^1.16.4",
"frappe-gantt": "^0.6.0",
"highlight.js": "^10.4.1",


+ 1
- 0
pyproject.toml Ver fichero

@@ -109,3 +109,4 @@ coverage = "~=6.4.1"
Faker = "~=13.12.1"
pyngrok = "~=5.0.5"
unittest-xml-reporting = "~=3.0.4"
watchdog = "~=2.1.9"

+ 4
- 4
yarn.lock Ver fichero

@@ -1256,10 +1256,10 @@ fraction.js@^4.1.2:
resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.2.0.tgz#448e5109a313a3527f5a3ab2119ec4cf0e0e2950"
integrity sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==

frappe-charts@^2.0.0-rc13:
version "2.0.0-rc13"
resolved "https://registry.yarnpkg.com/frappe-charts/-/frappe-charts-2.0.0-rc13.tgz#fdb251d7ae311c41e38f90a3ae108070ec6b9072"
integrity sha512-Bv7IfllIrjRbKWHn5b769dOSenqdBixAr6m5kurf8ZUOJSLOgK4HOXItJ7BA8n9PvviH9/k5DaloisjLM2Bm1w==
frappe-charts@^2.0.0-rc22:
version "2.0.0-rc22"
resolved "https://registry.yarnpkg.com/frappe-charts/-/frappe-charts-2.0.0-rc22.tgz#9a5a747febdc381a1d4d7af96e89cf519dfba8c0"
integrity sha512-N7f/8979wJCKjusOinaUYfMxB80YnfuVLrSkjpj4LtyqS0BGS6SuJxUnb7Jl4RWUFEIs7zEhideIKnyLeFZF4Q==

frappe-datatable@^1.16.4:
version "1.16.4"


Cargando…
Cancelar
Guardar