Merge branch 'develop' into link_title_refactor

This commit is contained in:
Suraj Shetty 2022-02-07 12:45:48 +05:30 committed by GitHub
commit ce791aef5f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 42 additions and 372 deletions

View file

@ -354,7 +354,6 @@ class TestDocType(unittest.TestCase):
dump_docs = json.dumps(docs.get('docs'))
cancel_all_linked_docs(dump_docs)
data_link_doc.cancel()
data_doc.name = '{}-CANC-0'.format(data_doc.name)
data_doc.load_from_db()
self.assertEqual(data_link_doc.docstatus, 2)
self.assertEqual(data_doc.docstatus, 2)
@ -378,7 +377,7 @@ class TestDocType(unittest.TestCase):
for data in link_doc.get('permissions'):
data.submit = 1
data.cancel = 1
link_doc.insert(ignore_if_duplicate=True)
link_doc.insert()
#create first parent doctype
test_doc_1 = new_doctype('Test Doctype 1')
@ -393,7 +392,7 @@ class TestDocType(unittest.TestCase):
for data in test_doc_1.get('permissions'):
data.submit = 1
data.cancel = 1
test_doc_1.insert(ignore_if_duplicate=True)
test_doc_1.insert()
#crete second parent doctype
doc = new_doctype('Test Doctype 2')
@ -408,7 +407,7 @@ class TestDocType(unittest.TestCase):
for data in link_doc.get('permissions'):
data.submit = 1
data.cancel = 1
doc.insert(ignore_if_duplicate=True)
doc.insert()
# create doctype data
data_link_doc_1 = frappe.new_doc('Test Linked Doctype 1')
@ -439,7 +438,6 @@ class TestDocType(unittest.TestCase):
# checking that doc for Test Doctype 2 is not canceled
self.assertRaises(frappe.LinkExistsError, data_link_doc_1.cancel)
data_doc_2.name = '{}-CANC-0'.format(data_doc_2.name)
data_doc.load_from_db()
data_doc_2.load_from_db()
self.assertEqual(data_link_doc_1.docstatus, 2)

View file

@ -9,7 +9,7 @@ import frappe
from frappe import _, msgprint, is_whitelisted
from frappe.utils import flt, cstr, now, get_datetime_str, file_lock, date_diff
from frappe.model.base_document import BaseDocument, get_controller
from frappe.model.naming import set_new_name, gen_new_name_for_cancelled_doc
from frappe.model.naming import set_new_name
from frappe.model.docstatus import DocStatus
from frappe.model import optional_fields, table_fields
from frappe.model.workflow import validate_workflow
@ -311,9 +311,6 @@ class Document(BaseDocument):
self.check_permission("write", "save")
if self.docstatus.is_cancelled():
self._rename_doc_on_cancel()
self.set_user_and_timestamp()
self.set_docstatus()
self.check_if_latest()
@ -724,6 +721,7 @@ class Document(BaseDocument):
else:
tmp = frappe.db.sql("""select modified, docstatus from `tab{0}`
where name = %s for update""".format(self.doctype), self.name, as_dict=True)
if not tmp:
frappe.throw(_("Record does not exist"))
else:
@ -1376,11 +1374,6 @@ class Document(BaseDocument):
from frappe.desk.doctype.tag.tag import DocTags
return DocTags(self.doctype).get_tags(self.name).split(",")[1:]
def _rename_doc_on_cancel(self):
new_name = gen_new_name_for_cancelled_doc(self)
frappe.rename_doc(self.doctype, self.name, new_name, force=True, show_alert=False)
self.name = new_name
def __repr__(self):
name = self.name or "unsaved"
doctype = self.__class__.__name__

View file

@ -1,14 +1,3 @@
"""utilities to generate a document name based on various rules defined.
NOTE:
Till version 13, whenever a submittable document is amended it's name is set to orig_name-X,
where X is a counter and it increments when amended again and so on.
From Version 14, The naming pattern is changed in a way that amended documents will
have the original name `orig_name` instead of `orig_name-X`. To make this happen
the cancelled document naming pattern is changed to 'orig_name-CANC-X'.
"""
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: MIT. See LICENSE
@ -40,7 +29,7 @@ def set_new_name(doc):
doc.name = None
if getattr(doc, "amended_from", None):
doc.name = _get_amended_name(doc)
_set_amended_name(doc)
return
elif getattr(doc.meta, "issingle", False):
@ -256,18 +245,6 @@ def revert_series_if_last(key, name, doc=None):
* prefix = #### and hashes = 2021 (hash doesn't exist)
* will search hash in key then accordingly get prefix = ""
"""
if hasattr(doc, 'amended_from'):
# Do not revert the series if the document is amended.
if doc.amended_from:
return
# Get document name by parsing incase of fist cancelled document
if doc.docstatus == 2 and not doc.amended_from:
if doc.name.endswith('-CANC'):
name, _ = NameParser.parse_docname(doc.name, sep='-CANC')
else:
name, _ = NameParser.parse_docname(doc.name, sep='-CANC-')
if ".#" in key:
prefix, hashes = key.rsplit(".", 1)
if "#" not in hashes:
@ -356,9 +333,16 @@ def append_number_if_name_exists(doctype, value, fieldname="name", separator="-"
return value
def _get_amended_name(doc):
name, _ = NameParser(doc).parse_amended_from()
return name
def _set_amended_name(doc):
am_id = 1
am_prefix = doc.amended_from
if frappe.db.get_value(doc.doctype, doc.amended_from, "amended_from"):
am_id = cint(doc.amended_from.split("-")[-1]) + 1
am_prefix = "-".join(doc.amended_from.split("-")[:-1]) # except the last hyphen
doc.name = am_prefix + "-" + str(am_id)
return doc.name
def _field_autoname(autoname, doc, skip_slicing=None):
"""
@ -399,83 +383,3 @@ def _format_autoname(autoname, doc):
name = re.sub(r"(\{[\w | #]+\})", get_param_value_for_match, autoname_value)
return name
class NameParser:
"""Parse document name and return parts of it.
NOTE: It handles cancellend and amended doc parsing for now. It can be expanded.
"""
def __init__(self, doc):
self.doc = doc
def parse_amended_from(self):
"""
Cancelled document naming will be in one of these formats
* original_name-X-CANC - This is introduced to migrate old style naming to new style
* original_name-CANC - This is introduced to migrate old style naming to new style
* original_name-CANC-X - This is the new style naming
New style naming: In new style naming amended documents will have original name. That says,
when a document gets cancelled we need rename the document by adding `-CANC-X` to the end
so that amended documents can use the original name.
Old style naming: cancelled documents stay with original name and when amended, amended one
gets a new name as `original_name-X`. To bring new style naming we had to change the existing
cancelled document names and that is done by adding `-CANC` to cancelled documents through patch.
"""
if not getattr(self.doc, 'amended_from', None):
return (None, None)
# Handle old style cancelled documents (original_name-X-CANC, original_name-CANC)
if self.doc.amended_from.endswith('-CANC'):
name, _ = self.parse_docname(self.doc.amended_from, '-CANC')
amended_from_doc = frappe.get_all(
self.doc.doctype,
filters = {'name': self.doc.amended_from},
fields = ['amended_from'],
limit=1)
# Handle format original_name-X-CANC.
if amended_from_doc and amended_from_doc[0].amended_from:
return self.parse_docname(name, '-')
return name, None
# Handle new style cancelled documents
return self.parse_docname(self.doc.amended_from, '-CANC-')
@classmethod
def parse_docname(cls, name, sep='-'):
split_list = name.rsplit(sep, 1)
if len(split_list) == 1:
return (name, None)
return (split_list[0], split_list[1])
def get_cancelled_doc_latest_counter(tname, docname):
"""Get the latest counter used for cancelled docs of given docname.
"""
name_prefix = f'{docname}-CANC-'
rows = frappe.db.sql("""
select
name
from `tab{tname}`
where
name like %(name_prefix)s and docstatus=2
""".format(tname=tname), {'name_prefix': name_prefix+'%'}, as_dict=1)
if not rows:
return -1
return max([int(row.name.replace(name_prefix, '') or -1) for row in rows])
def gen_new_name_for_cancelled_doc(doc):
"""Generate a new name for cancelled document.
"""
if getattr(doc, "amended_from", None):
name, _ = NameParser(doc).parse_amended_from()
else:
name = doc.name
counter = get_cancelled_doc_latest_counter(doc.doctype, name)
return f'{name}-CANC-{counter+1}'

View file

@ -185,7 +185,6 @@ frappe.patches.v13_0.queryreport_columns
frappe.patches.v13_0.jinja_hook
frappe.patches.v13_0.update_notification_channel_if_empty
frappe.patches.v13_0.set_first_day_of_the_week
frappe.patches.v14_0.rename_cancelled_documents
frappe.patches.v14_0.update_workspace2 # 20.09.2021
frappe.patches.v14_0.save_ratings_in_fraction #23-12-2021
frappe.patches.v14_0.transform_todo_schema

View file

@ -1,213 +0,0 @@
import functools
import traceback
import frappe
def execute():
"""Rename cancelled documents by adding a postfix.
"""
rename_cancelled_docs()
def get_submittable_doctypes():
"""Returns list of submittable doctypes in the system.
"""
return frappe.db.get_all('DocType', filters={'is_submittable': 1}, pluck='name')
def get_cancelled_doc_names(doctype):
"""Return names of cancelled document names those are in old format.
"""
docs = frappe.db.get_all(doctype, filters={'docstatus': 2}, pluck='name')
return [each for each in docs if not (each.endswith('-CANC') or ('-CANC-' in each))]
@functools.lru_cache()
def get_linked_doctypes():
"""Returns list of doctypes those are linked with given doctype using 'Link' fieldtype.
"""
filters=[['fieldtype','=', 'Link']]
links = frappe.get_all("DocField",
fields=["parent", "fieldname", "options as linked_to"],
filters=filters,
as_list=1)
links+= frappe.get_all("Custom Field",
fields=["dt as parent", "fieldname", "options as linked_to"],
filters=filters,
as_list=1)
links_by_doctype = {}
for doctype, fieldname, linked_to in links:
links_by_doctype.setdefault(linked_to, []).append((doctype, fieldname))
return links_by_doctype
@functools.lru_cache()
def get_single_doctypes():
return frappe.get_all("DocType", filters={'issingle': 1}, pluck='name')
@functools.lru_cache()
def get_dynamic_linked_doctypes():
filters=[['fieldtype','=', 'Dynamic Link']]
# find dynamic links of parents
links = frappe.get_all("DocField",
fields=["parent as doctype", "fieldname", "options as doctype_fieldname"],
filters=filters,
as_list=1)
links+= frappe.get_all("Custom Field",
fields=["dt as doctype", "fieldname", "options as doctype_fieldname"],
filters=filters,
as_list=1)
return links
@functools.lru_cache()
def get_child_tables():
"""
"""
filters =[['fieldtype', 'in', ('Table', 'Table MultiSelect')]]
links = frappe.get_all("DocField",
fields=["parent as doctype", "options as child_table"],
filters=filters,
as_list=1)
links+= frappe.get_all("Custom Field",
fields=["dt as doctype", "options as child_table"],
filters=filters,
as_list=1)
map = {}
for doctype, child_table in links:
map.setdefault(doctype, []).append(child_table)
return map
def update_cancelled_document_names(doctype, cancelled_doc_names):
return frappe.db.sql("""
update
`tab{doctype}`
set
name=CONCAT(name, '-CANC')
where
docstatus=2
and
name in %(cancelled_doc_names)s;
""".format(doctype=doctype), {'cancelled_doc_names': cancelled_doc_names})
def update_amended_field(doctype, cancelled_doc_names):
return frappe.db.sql("""
update
`tab{doctype}`
set
amended_from=CONCAT(amended_from, '-CANC')
where
amended_from in %(cancelled_doc_names)s;
""".format(doctype=doctype), {'cancelled_doc_names': cancelled_doc_names})
def update_attachments(doctype, cancelled_doc_names):
frappe.db.sql("""
update
`tabFile`
set
attached_to_name=CONCAT(attached_to_name, '-CANC')
where
attached_to_doctype=%(dt)s and attached_to_name in %(cancelled_doc_names)s
""", {'cancelled_doc_names': cancelled_doc_names, 'dt': doctype})
def update_versions(doctype, cancelled_doc_names):
frappe.db.sql("""
UPDATE
`tabVersion`
SET
docname=CONCAT(docname, '-CANC')
WHERE
ref_doctype=%(dt)s AND docname in %(cancelled_doc_names)s
""", {'cancelled_doc_names': cancelled_doc_names, 'dt': doctype})
def update_linked_doctypes(doctype, cancelled_doc_names):
single_doctypes = get_single_doctypes()
for linked_dt, field in get_linked_doctypes().get(doctype, []):
if linked_dt not in single_doctypes:
frappe.db.sql("""
update
`tab{linked_dt}`
set
`{column}`=CONCAT(`{column}`, '-CANC')
where
`{column}` in %(cancelled_doc_names)s;
""".format(linked_dt=linked_dt, column=field),
{'cancelled_doc_names': cancelled_doc_names})
else:
doc = frappe.get_single(linked_dt)
if getattr(doc, field) in cancelled_doc_names:
setattr(doc, field, getattr(doc, field)+'-CANC')
doc.flags.ignore_mandatory=True
doc.flags.ignore_validate=True
doc.save(ignore_permissions=True)
def update_dynamic_linked_doctypes(doctype, cancelled_doc_names):
single_doctypes = get_single_doctypes()
for linked_dt, fieldname, doctype_fieldname in get_dynamic_linked_doctypes():
if linked_dt not in single_doctypes:
frappe.db.sql("""
update
`tab{linked_dt}`
set
`{column}`=CONCAT(`{column}`, '-CANC')
where
`{column}` in %(cancelled_doc_names)s and {doctype_fieldname}=%(dt)s;
""".format(linked_dt=linked_dt, column=fieldname, doctype_fieldname=doctype_fieldname),
{'cancelled_doc_names': cancelled_doc_names, 'dt': doctype})
else:
doc = frappe.get_single(linked_dt)
if getattr(doc, doctype_fieldname) == doctype and getattr(doc, fieldname) in cancelled_doc_names:
setattr(doc, fieldname, getattr(doc, fieldname)+'-CANC')
doc.flags.ignore_mandatory=True
doc.flags.ignore_validate=True
doc.save(ignore_permissions=True)
def update_child_tables(doctype, cancelled_doc_names):
child_tables = get_child_tables().get(doctype, [])
single_doctypes = get_single_doctypes()
for table in child_tables:
if table not in single_doctypes:
frappe.db.sql("""
update
`tab{table}`
set
parent=CONCAT(parent, '-CANC')
where
parenttype=%(dt)s and parent in %(cancelled_doc_names)s;
""".format(table=table), {'cancelled_doc_names': cancelled_doc_names, 'dt': doctype})
else:
doc = frappe.get_single(table)
if getattr(doc, 'parenttype')==doctype and getattr(doc, 'parent') in cancelled_doc_names:
setattr(doc, 'parent', getattr(doc, 'parent')+'-CANC')
doc.flags.ignore_mandatory=True
doc.flags.ignore_validate=True
doc.save(ignore_permissions=True)
def rename_cancelled_docs():
submittable_doctypes = get_submittable_doctypes()
for dt in submittable_doctypes:
for retry in range(2):
try:
cancelled_doc_names = tuple(get_cancelled_doc_names(dt))
if not cancelled_doc_names:
break
update_cancelled_document_names(dt, cancelled_doc_names)
update_amended_field(dt, cancelled_doc_names)
update_child_tables(dt, cancelled_doc_names)
update_linked_doctypes(dt, cancelled_doc_names)
update_dynamic_linked_doctypes(dt, cancelled_doc_names)
update_attachments(dt, cancelled_doc_names)
update_versions(dt, cancelled_doc_names)
print(f"Renaming cancelled records of {dt} doctype")
frappe.db.commit()
break
except Exception:
if retry == 1:
print(f"Failed to rename the cancelled records of {dt} doctype, moving on!")
traceback.print_exc()
frappe.db.rollback()

View file

@ -860,36 +860,32 @@ frappe.ui.form.Form = class FrappeForm {
}
_cancel(btn, callback, on_error, skip_confirm) {
const me = this;
const cancel_doc = () => {
frappe.validated = true;
this.script_manager.trigger("before_cancel").then(() => {
me.script_manager.trigger("before_cancel").then(() => {
if (!frappe.validated) {
return this.handle_save_fail(btn, on_error);
return me.handle_save_fail(btn, on_error);
}
const original_name = this.docname;
const after_cancel = (r) => {
var after_cancel = function(r) {
if (r.exc) {
this.handle_save_fail(btn, on_error);
me.handle_save_fail(btn, on_error);
} else {
frappe.utils.play_sound("cancel");
me.refresh();
callback && callback();
this.script_manager.trigger("after_cancel");
frappe.run_serially([
() => this.rename_notify(this.doctype, original_name, r.docs[0].name),
() => frappe.router.clear_re_route(this.doctype, original_name),
() => this.refresh(),
]);
me.script_manager.trigger("after_cancel");
}
};
frappe.ui.form.save(this, "cancel", after_cancel, btn);
frappe.ui.form.save(me, "cancel", after_cancel, btn);
});
}
if (skip_confirm) {
cancel_doc();
} else {
frappe.confirm(__("Permanently Cancel {0}?", [this.docname]), cancel_doc, this.handle_save_fail(btn, on_error));
frappe.confirm(__("Permanently Cancel {0}?", [this.docname]), cancel_doc, me.handle_save_fail(btn, on_error));
}
};
@ -911,7 +907,7 @@ frappe.ui.form.Form = class FrappeForm {
'docname': this.doc.name
}).then(is_amended => {
if (is_amended) {
frappe.throw(__('This document is already amended, you cannot amend it again'));
frappe.throw(__('This document is already amended, you cannot ammend it again'));
}
this.validate_form_action("Amend");
var me = this;

View file

@ -250,12 +250,6 @@ frappe.router = {
}
},
clear_re_route(doctype, docname) {
delete frappe.re_route[
`${encodeURIComponent(frappe.router.slug(doctype))}/${encodeURIComponent(docname)}`
];
},
set_title(sub_path) {
if (frappe.route_titles[sub_path]) {
frappe.utils.set_title(frappe.route_titles[sub_path]);

View file

@ -66,7 +66,7 @@ class FullTextSearch:
ix = self.get_index()
with ix.searcher():
writer = ix.writer()
writer = AsyncWriter(ix)
writer.delete_by_term(self.id, doc_name)
writer.commit(optimize=True)
@ -98,7 +98,7 @@ class FullTextSearch:
def build_index(self):
"""Build index for all parsed documents"""
ix = self.create_index()
writer = ix.writer()
writer = AsyncWriter(ix)
for i, document in enumerate(self.documents):
if document:

View file

@ -144,6 +144,7 @@ class TestNaming(unittest.TestCase):
current_index = frappe.db.sql("""SELECT current from `tabSeries` where name = %s""", series, as_dict=True)[0]
self.assertEqual(current_index.get('current'), 2)
frappe.db.delete("Series", {"name": series})
def test_naming_for_cancelled_and_amended_doc(self):
@ -166,25 +167,20 @@ class TestNaming(unittest.TestCase):
doc.submit()
doc.cancel()
cancelled_name = doc.name
self.assertEqual(cancelled_name, "{}-CANC-0".format(original_name))
self.assertEqual(cancelled_name, original_name)
amended_doc = frappe.copy_doc(doc)
amended_doc.docstatus = 0
amended_doc.amended_from = doc.name
amended_doc.save()
self.assertEqual(amended_doc.name, original_name)
self.assertEqual(amended_doc.name, "{}-1".format(original_name))
amended_doc.submit()
amended_doc.cancel()
self.assertEqual(amended_doc.name, "{}-CANC-1".format(original_name))
self.assertEqual(amended_doc.name, "{}-1".format(original_name))
submittable_doctype.delete()
def test_parse_naming_series_for_consecutive_week_number(self):
week = determine_consecutive_week_number(now_datetime())
name = parse_naming_series('PREFIX-.WW.-SUFFIX')
expected_name = 'PREFIX-{}-SUFFIX'.format(week)
self.assertEqual(name, expected_name)
def test_determine_consecutive_week_number(self):
from datetime import datetime
@ -207,4 +203,4 @@ class TestNaming(unittest.TestCase):
dt = datetime.fromisoformat("2021-12-31")
w = determine_consecutive_week_number(dt)
self.assertEqual(w, "52")
self.assertEqual(w, "52")

View file

@ -151,6 +151,7 @@ My Account,Mein Konto,
New Address,Neue Adresse,
New Contact,Neuer Kontakt,
Next,Weiter,
No,Nein,
No Data,Keine Daten,
No address added yet.,Noch keine Adresse hinzugefügt.,
No contacts added yet.,Noch keine Kontakte hinzugefügt.,
@ -349,7 +350,7 @@ Add a New Role,Neue Rolle hinzufügen,
Add a column,Spalte einfügen,
Add a comment,Einen Kommentar hinzufügen,
Add a new section,Fügen Sie einen neuen Abschnitt hinzu,
Add a tag ...,Füge einen Tag hinzu ...,
Add a tag ...,Füge ein Schlagwort hinzu ...,
Add all roles,Alle Rollen hinzufügen,
Add custom forms.,Benutzerdefinierte Formulare hinzufügen,
Add custom javascript to forms.,Benutzerdefiniertes Javascript zum Formular hinzufügen,
@ -946,6 +947,7 @@ Edit Auto Email Report Settings,Bearbeiten Sie die Einstellungen für automatisc
Edit Custom HTML,Benutzerdefiniertes HTML bearbeiten,
Edit DocType,DocType bearbeiten,
Edit Filter,Filter bearbeiten,
Edit Filters,Filter bearbeiten,
Edit Format,Format bearbeiten,
Edit HTML,HTML bearbeiten,
Edit Heading,Kopf bearbeiten,
@ -1230,6 +1232,7 @@ Hide Copy,Kopie ausblenden,
Hide Footer Signup,Fußzeilen-Anmeldung ausblenden,
Hide Sidebar and Menu,Seitenleiste und Menü ausblenden,
Hide Standard Menu,Standardmenü ausblenden,
Hide Tags,Schlagworte ausblenden,
Hide Weekends,Wochenenden ausblenden,
Hide details,Details ausblenden,
Hide footer in auto email reports,Fußzeile in automatischen E-Mail-Berichten ausblenden,
@ -1650,7 +1653,7 @@ No Preview,Keine Vorschau,
No Preview Available,Keine Vorschau vorhanden,
No Printer is Available.,Es ist kein Drucker verfügbar.,
No Results,Keine Ergebnisse,
No Tags,No Tags,
No Tags,Keine Schlagworte,
No alerts for today,Keine Warnungen für heute,
No comments yet,Noch keine Kommentare,
No comments yet. Start a new discussion.,Noch keine Kommentare. Starten Sie eine neue Diskussion.,
@ -2040,7 +2043,7 @@ Remove,Entfernen,
Remove Field,Feld entfernen,
Remove Filter,Filter entfernen,
Remove Section,Abschnitt entfernen,
Remove Tag,Markierung entfernen,
Remove Tag,Schlagwort entfernen,
Remove all customizations?,Alle Anpassungen entfernen?,
Removed {0},{0} entfernt,
Rename many items by uploading a .csv file.,Viele Elemente auf einmal umbenennen durch Hochladen einer .CSV-Datei,
@ -3250,7 +3253,7 @@ DocType Action,DocType-Aktion,
DocType Event,DocType-Ereignis,
DocType Link,DocType Link,
Document Share,Dokumentenfreigabe,
Document Tag,Dokument-Tag,
Document Tag,Dokument-Schlagwort,
Document Title,Dokumenttitel,
Document Type Field Mapping,Dokumenttyp-Feldzuordnung,
Document Type Mapping,Dokumenttypzuordnung,
@ -3796,7 +3799,7 @@ Start,Start,
Start Time,Startzeit,
Status,Status,
Submitted,Gebucht,
Tag,Etikett,
Tag,Schlagwort,
Template,Vorlage,
Thursday,Donnerstag,
Title,Bezeichnung,
@ -4028,7 +4031,7 @@ Please select target language for translation,Bitte wählen Sie die Zielsprache
Select Language,Sprache auswählen,
Confirm Translations,Übersetzungen bestätigen,
Contributed Translations,Beigetragene Übersetzungen,
Show Tags,Tags anzeigen,
Show Tags,Schlagworte anzeigen,
Do not have permission to access {0} bucket.,Sie haben keine Berechtigung zum Zugriff auf den Bucket {0}.,
Allow document creation via Email,Dokumenterstellung per E-Mail zulassen,
Sender Field,Absenderfeld,

1 A4 A4
151 New Address Neue Adresse
152 New Contact Neuer Kontakt
153 Next Weiter
154 No Nein
155 No Data Keine Daten
156 No address added yet. Noch keine Adresse hinzugefügt.
157 No contacts added yet. Noch keine Kontakte hinzugefügt.
350 Add a column Spalte einfügen
351 Add a comment Einen Kommentar hinzufügen
352 Add a new section Fügen Sie einen neuen Abschnitt hinzu
353 Add a tag ... Füge einen Tag hinzu ... Füge ein Schlagwort hinzu ...
354 Add all roles Alle Rollen hinzufügen
355 Add custom forms. Benutzerdefinierte Formulare hinzufügen
356 Add custom javascript to forms. Benutzerdefiniertes Javascript zum Formular hinzufügen
947 Edit Custom HTML Benutzerdefiniertes HTML bearbeiten
948 Edit DocType DocType bearbeiten
949 Edit Filter Filter bearbeiten
950 Edit Filters Filter bearbeiten
951 Edit Format Format bearbeiten
952 Edit HTML HTML bearbeiten
953 Edit Heading Kopf bearbeiten
1232 Hide Footer Signup Fußzeilen-Anmeldung ausblenden
1233 Hide Sidebar and Menu Seitenleiste und Menü ausblenden
1234 Hide Standard Menu Standardmenü ausblenden
1235 Hide Tags Schlagworte ausblenden
1236 Hide Weekends Wochenenden ausblenden
1237 Hide details Details ausblenden
1238 Hide footer in auto email reports Fußzeile in automatischen E-Mail-Berichten ausblenden
1653 No Preview Available Keine Vorschau vorhanden
1654 No Printer is Available. Es ist kein Drucker verfügbar.
1655 No Results Keine Ergebnisse
1656 No Tags No Tags Keine Schlagworte
1657 No alerts for today Keine Warnungen für heute
1658 No comments yet Noch keine Kommentare
1659 No comments yet. Start a new discussion. Noch keine Kommentare. Starten Sie eine neue Diskussion.
2043 Remove Field Feld entfernen
2044 Remove Filter Filter entfernen
2045 Remove Section Abschnitt entfernen
2046 Remove Tag Markierung entfernen Schlagwort entfernen
2047 Remove all customizations? Alle Anpassungen entfernen?
2048 Removed {0} {0} entfernt
2049 Rename many items by uploading a .csv file. Viele Elemente auf einmal umbenennen durch Hochladen einer .CSV-Datei
3253 DocType Event DocType-Ereignis
3254 DocType Link DocType Link
3255 Document Share Dokumentenfreigabe
3256 Document Tag Dokument-Tag Dokument-Schlagwort
3257 Document Title Dokumenttitel
3258 Document Type Field Mapping Dokumenttyp-Feldzuordnung
3259 Document Type Mapping Dokumenttypzuordnung
3799 Start Time Startzeit
3800 Status Status
3801 Submitted Gebucht
3802 Tag Etikett Schlagwort
3803 Template Vorlage
3804 Thursday Donnerstag
3805 Title Bezeichnung
4031 Select Language Sprache auswählen
4032 Confirm Translations Übersetzungen bestätigen
4033 Contributed Translations Beigetragene Übersetzungen
4034 Show Tags Tags anzeigen Schlagworte anzeigen
4035 Do not have permission to access {0} bucket. Sie haben keine Berechtigung zum Zugriff auf den Bucket {0}.
4036 Allow document creation via Email Dokumenterstellung per E-Mail zulassen
4037 Sender Field Absenderfeld