* [enhance] set doctype label via Customize Form frappe/erpnext#2019 * Update customize_form.pyversion-14
@@ -56,8 +56,6 @@ def get_lang_dict(fortype, name=None): | |||
:param fortype: must be one of `doctype`, `page`, `report`, `include`, `jsfile`, `boot` | |||
:param name: name of the document for which assets are to be returned.""" | |||
if local.lang=="en": | |||
return {} | |||
from frappe.translate import get_dict | |||
return get_dict(fortype, name) | |||
@@ -103,16 +103,18 @@ def get_allowed_pages(): | |||
return page_info | |||
def load_translations(bootinfo): | |||
if frappe.local.lang != 'en': | |||
messages = frappe.get_lang_dict("boot") | |||
messages = frappe.get_lang_dict("boot") | |||
bootinfo["lang"] = frappe.lang | |||
bootinfo["lang"] = frappe.lang | |||
# load translated report names | |||
for name in bootinfo.user.all_reports: | |||
messages[name] = frappe._(name) | |||
# load translated report names | |||
for name in bootinfo.user.all_reports: | |||
messages[name] = frappe._(name) | |||
bootinfo["__messages"] = messages | |||
# only untranslated | |||
messages = {k:v for k, v in messages.iteritems() if k!=v} | |||
bootinfo["__messages"] = messages | |||
def get_fullnames(): | |||
"""map of user fullnames""" | |||
@@ -5,10 +5,11 @@ | |||
from __future__ import unicode_literals | |||
import frappe | |||
from frappe.model.document import Document | |||
from frappe.translate import clear_cache | |||
class Translation(Document): | |||
def on_update(self): | |||
frappe.cache().hdel('lang_user_translations', self.language_code) | |||
clear_cache() | |||
def on_trash(self): | |||
frappe.cache().hdel('lang_user_translations', self.language_code) | |||
clear_cache() |
@@ -9,6 +9,7 @@ frappe.ui.form.on("Customize Form", { | |||
frm.set_query("doc_type", function() { | |||
return { | |||
translate_values: false, | |||
filters: [ | |||
['DocType', 'issingle', '=', 0], | |||
['DocType', 'custom', '=', 0], | |||
@@ -15,6 +15,7 @@ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "doc_type", | |||
"fieldtype": "Link", | |||
"hidden": 0, | |||
@@ -40,6 +41,7 @@ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"depends_on": "doc_type", | |||
"fieldname": "properties", | |||
"fieldtype": "Section Break", | |||
@@ -65,6 +67,33 @@ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "label", | |||
"fieldtype": "Data", | |||
"hidden": 0, | |||
"ignore_user_permissions": 0, | |||
"ignore_xss_filter": 0, | |||
"in_filter": 0, | |||
"in_list_view": 0, | |||
"label": "Change Label (via Custom Translation)", | |||
"length": 0, | |||
"no_copy": 0, | |||
"permlevel": 0, | |||
"precision": "", | |||
"print_hide": 0, | |||
"print_hide_if_no_value": 0, | |||
"read_only": 0, | |||
"report_hide": 0, | |||
"reqd": 0, | |||
"search_index": 0, | |||
"set_only_once": 0, | |||
"unique": 0 | |||
}, | |||
{ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "default_print_format", | |||
"fieldtype": "Link", | |||
"hidden": 0, | |||
@@ -90,6 +119,7 @@ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"depends_on": "", | |||
"fieldname": "max_attachments", | |||
"fieldtype": "Int", | |||
@@ -115,6 +145,7 @@ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "allow_copy", | |||
"fieldtype": "Check", | |||
"hidden": 0, | |||
@@ -139,6 +170,7 @@ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "istable", | |||
"fieldtype": "Check", | |||
"hidden": 0, | |||
@@ -164,6 +196,7 @@ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"depends_on": "istable", | |||
"fieldname": "editable_grid", | |||
"fieldtype": "Check", | |||
@@ -190,6 +223,7 @@ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"default": "1", | |||
"fieldname": "quick_entry", | |||
"fieldtype": "Check", | |||
@@ -216,6 +250,7 @@ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"depends_on": "eval: doc.image_field", | |||
"fieldname": "image_view", | |||
"fieldtype": "Check", | |||
@@ -242,6 +277,7 @@ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "column_break_5", | |||
"fieldtype": "Column Break", | |||
"hidden": 0, | |||
@@ -266,6 +302,7 @@ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"description": "Use this fieldname to generate title", | |||
"fieldname": "title_field", | |||
"fieldtype": "Data", | |||
@@ -292,6 +329,7 @@ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"description": "Must be of type \"Attach Image\"", | |||
"fieldname": "image_field", | |||
"fieldtype": "Data", | |||
@@ -318,6 +356,7 @@ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"description": "Fields separated by comma (,) will be included in the \"Search By\" list of Search dialog box", | |||
"fieldname": "search_fields", | |||
"fieldtype": "Data", | |||
@@ -343,6 +382,7 @@ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"depends_on": "doc_type", | |||
"fieldname": "section_break_8", | |||
"fieldtype": "Section Break", | |||
@@ -368,6 +408,7 @@ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "sort_field", | |||
"fieldtype": "Select", | |||
"hidden": 0, | |||
@@ -392,6 +433,7 @@ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "column_break_10", | |||
"fieldtype": "Column Break", | |||
"hidden": 0, | |||
@@ -416,6 +458,7 @@ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "sort_order", | |||
"fieldtype": "Select", | |||
"hidden": 0, | |||
@@ -441,6 +484,7 @@ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"depends_on": "doc_type", | |||
"description": "Customize Label, Print Hide, Default etc.", | |||
"fieldname": "fields_section_break", | |||
@@ -467,6 +511,7 @@ | |||
"allow_on_submit": 0, | |||
"bold": 0, | |||
"collapsible": 0, | |||
"columns": 0, | |||
"fieldname": "fields", | |||
"fieldtype": "Table", | |||
"hidden": 0, | |||
@@ -500,7 +545,7 @@ | |||
"issingle": 1, | |||
"istable": 0, | |||
"max_attachments": 0, | |||
"modified": "2016-07-08 04:40:57.045612", | |||
"modified": "2016-09-16 02:36:09.171273", | |||
"modified_by": "Administrator", | |||
"module": "Custom", | |||
"name": "Customize Form", | |||
@@ -7,6 +7,7 @@ from __future__ import unicode_literals | |||
Thus providing a better UI from user perspective | |||
""" | |||
import frappe | |||
import frappe.translate | |||
from frappe import _ | |||
from frappe.utils import cint | |||
from frappe.model.document import Document | |||
@@ -84,8 +85,36 @@ class CustomizeForm(Document): | |||
new_d[property] = d.get(property) | |||
self.append("fields", new_d) | |||
# load custom translation | |||
translation = self.get_name_translation() | |||
self.label = translation.target_name if translation else '' | |||
# NOTE doc is sent to clientside by run_method | |||
def get_name_translation(self): | |||
'''Get translation object if exists of current doctype name in the default language''' | |||
return frappe.get_value('Translation', | |||
{'source_name': self.doc_type, 'language_code': frappe.local.lang or 'en'}, | |||
['name', 'target_name'], as_dict=True) | |||
def set_name_translation(self): | |||
'''Create, update custom translation for this doctype''' | |||
current = self.get_name_translation() | |||
if current: | |||
if self.label and current!=self.label: | |||
frappe.db.set_value('Translation', current.name, 'target_name', self.label) | |||
frappe.translate.clear_cache() | |||
else: | |||
# clear translation | |||
frappe.delete_doc('Translation', current.name) | |||
else: | |||
if self.label: | |||
frappe.get_doc(dict(doctype='Translation', | |||
source_name=self.doc_type, | |||
target_name=self.label, | |||
language_code=frappe.local.lang or 'en')).insert() | |||
def clear_existing_doc(self): | |||
doc_type = self.doc_type | |||
@@ -104,6 +133,7 @@ class CustomizeForm(Document): | |||
self.set_property_setters() | |||
self.update_custom_fields() | |||
self.set_name_translation() | |||
validate_fields_for_doctype(self.doc_type) | |||
frappe.msgprint(_("{0} updated").format(_(self.doc_type))) | |||
@@ -1146,6 +1146,7 @@ frappe.ui.form.ControlLink = frappe.ui.form.ControlData.extend({ | |||
}); | |||
this.input = this.$input.get(0); | |||
this.has_input = true; | |||
this.translate_values = true; | |||
var me = this; | |||
this.setup_buttons(); | |||
this.setup_autocomplete(); | |||
@@ -1337,7 +1338,11 @@ frappe.ui.form.ControlLink = frappe.ui.form.ControlData.extend({ | |||
$(this).autocomplete("close"); | |||
}) | |||
.data('ui-autocomplete')._renderItem = function(ul, d) { | |||
var html = "<strong>" + __(d.value) + "</strong>"; | |||
var _value = d.value; | |||
if(me.translate_values) { | |||
_value = __(d.value) | |||
} | |||
var html = "<strong>" + _value + "</strong>"; | |||
if(d.description && d.value!==d.description) { | |||
html += '<br><span class="small">' + __(d.description) + '</span>'; | |||
} | |||
@@ -1387,14 +1392,23 @@ frappe.ui.form.ControlLink = frappe.ui.form.ControlData.extend({ | |||
} else if(typeof(get_query)==="string") { | |||
args.query = get_query; | |||
} else { | |||
// get_query by function | |||
var q = (get_query)(this.frm && this.frm.doc, this.doctype, this.docname); | |||
if (typeof(q)==="string") { | |||
// returns a string | |||
args.query = q; | |||
} else if($.isPlainObject(q)) { | |||
// returns a plain object with filters | |||
if(q.filters) { | |||
set_nulls(q.filters); | |||
} | |||
// turn off value translation | |||
if(q.translate_values !== undefined) { | |||
this.translate_values = q.translate_values; | |||
} | |||
// extend args for custom functions | |||
$.extend(args, q); | |||
@@ -116,7 +116,6 @@ frappe.ui.toolbar.Toolbar = Class.extend({ | |||
var link = links[i]; | |||
var url = link.url; | |||
var app_name = url.split('//', 2)[1].split('/', 2)[1]; | |||
console.log(app_name) | |||
var data_path = url.slice(url.indexOf('/user')); | |||
if(data_path.lastIndexOf('.')){ | |||
data_path = data_path.slice(0, data_path.lastIndexOf('.')); | |||
@@ -209,8 +209,12 @@ _f.Frm.prototype.get_files = function() { | |||
_f.Frm.prototype.set_query = function(fieldname, opt1, opt2) { | |||
if(opt2) { | |||
// on child table | |||
// set_query(fieldname, parent fieldname, query) | |||
this.fields_dict[opt1].grid.get_field(fieldname).get_query = opt2; | |||
} else { | |||
// on parent table | |||
// set_query(fieldname, query) | |||
this.fields_dict[fieldname].get_query = opt1; | |||
} | |||
} | |||
@@ -113,8 +113,13 @@ def get_dict(fortype, name=None): | |||
messages += frappe.db.sql("select 'Module:', label from `tabDesktop Icon` where standard=1 or owner=%s", | |||
frappe.session.user) | |||
translation_assets[asset_key] = make_dict_from_messages(messages) | |||
translation_assets[asset_key].update(get_dict_from_hooks(fortype, name)) | |||
message_dict = make_dict_from_messages(messages) | |||
message_dict.update(get_dict_from_hooks(fortype, name)) | |||
# remove untranslated | |||
message_dict = {k:v for k, v in message_dict.iteritems() if k!=v} | |||
translation_assets[asset_key] = message_dict | |||
cache.hset("translation_assets", frappe.local.lang, translation_assets) | |||
@@ -245,16 +250,17 @@ def get_user_translations(lang): | |||
return out | |||
# def get_user_translation_key(): | |||
# return 'lang_user_translations:{0}'.format(frappe.local.site) | |||
def clear_cache(): | |||
"""Clear all translation assets from :meth:`frappe.cache`""" | |||
cache = frappe.cache() | |||
cache.delete_key("langinfo") | |||
# clear translations saved in boot cache | |||
cache.delete_key("bootinfo") | |||
cache.delete_key("lang_full_dict") | |||
cache.delete_key("translation_assets") | |||
cache.delete_key("lang_user_translations") | |||
def get_messages_for_app(app): | |||
"""Returns all messages (list) for a specified `app`""" | |||