@@ -39,11 +39,18 @@ def __getattr__(self, key): | |||||
def _(msg): | def _(msg): | ||||
"""translate object in current lang, if exists""" | """translate object in current lang, if exists""" | ||||
if hasattr(local, 'translations'): | |||||
return local.translations.get(lang, {}).get(msg, msg) | |||||
return msg | |||||
if local.lang == "en": | |||||
return msg | |||||
from webnotes.translate import get_full_dict | |||||
return get_full_dict(local.lang).get(msg, msg) | |||||
def get_lang_dict(fortype, name=None): | |||||
if local.lang=="en": | |||||
return {} | |||||
from webnotes.translate import get_dict | |||||
return get_dict(fortype, name) | |||||
def set_user_lang(user, user_language=None): | def set_user_lang(user, user_language=None): | ||||
from webnotes.translate import get_lang_dict | from webnotes.translate import get_lang_dict | ||||
@@ -55,11 +62,6 @@ def set_user_lang(user, user_language=None): | |||||
if user_language in lang_dict: | if user_language in lang_dict: | ||||
local.lang = lang_dict[user_language] | local.lang = lang_dict[user_language] | ||||
def load_translations(module, doctype, name): | |||||
from webnotes.translate import load_doc_messages | |||||
load_doc_messages(module, doctype, name) | |||||
# local-globals | # local-globals | ||||
conn = local("conn") | conn = local("conn") | ||||
conf = local("conf") | conf = local("conf") | ||||
@@ -197,7 +199,7 @@ def connect(site=None, db_name=None): | |||||
from db import Database | from db import Database | ||||
if site: | if site: | ||||
init(site) | init(site) | ||||
local.conn = Database(user=db_name) | |||||
local.conn = Database(user=db_name or local.conf.db_name) | |||||
local.response = _dict() | local.response = _dict() | ||||
local.form_dict = _dict() | local.form_dict = _dict() | ||||
local.session = _dict() | local.session = _dict() | ||||
@@ -407,12 +409,13 @@ def get_module(modulename): | |||||
def scrub(txt): | def scrub(txt): | ||||
return txt.replace(' ','_').replace('-', '_').replace('/', '_').lower() | return txt.replace(' ','_').replace('-', '_').replace('/', '_').lower() | ||||
def get_module_path(module): | |||||
def get_module_path(module, *joins): | |||||
module = scrub(module) | module = scrub(module) | ||||
return get_pymodule_path(local.module_app[module] + "." + module) | |||||
return get_pymodule_path(local.module_app[module] + "." + module, *joins) | |||||
def get_pymodule_path(modulename, *joins): | def get_pymodule_path(modulename, *joins): | ||||
return os.path.join(os.path.dirname(get_module(modulename).__file__), *joins) | |||||
joins = [scrub(part) for part in joins] | |||||
return os.path.join(os.path.dirname(get_module(scrub(modulename)).__file__), *joins) | |||||
def get_module_list(app_name): | def get_module_list(app_name): | ||||
return get_file_items(os.path.join(os.path.dirname(get_module(app_name).__file__), "modules.txt")) | return get_file_items(os.path.join(os.path.dirname(get_module(app_name).__file__), "modules.txt")) | ||||
@@ -430,17 +433,19 @@ def get_installed_apps(): | |||||
return json.loads(conn.get_global("installed_apps") or "[]") | return json.loads(conn.get_global("installed_apps") or "[]") | ||||
return cache().get_value("installed_apps", load_installed_apps) | return cache().get_value("installed_apps", load_installed_apps) | ||||
def get_hooks(): | |||||
def load_app_hooks(): | |||||
def get_hooks(app_name=None): | |||||
def load_app_hooks(app_name=None): | |||||
hooks = {} | hooks = {} | ||||
for app in get_installed_apps(): | |||||
for app in [app_name] if app_name else get_installed_apps(): | |||||
for item in get_file_items(get_pymodule_path(app, "hooks.txt")): | for item in get_file_items(get_pymodule_path(app, "hooks.txt")): | ||||
key, value = item.split(None, 1) | key, value = item.split(None, 1) | ||||
hooks.setdefault(key, []) | hooks.setdefault(key, []) | ||||
hooks[key].append(value) | hooks[key].append(value) | ||||
return hooks | return hooks | ||||
return _dict(cache().get_value("app_hooks", load_app_hooks)) | |||||
if app_name: | |||||
return _dict(load_app_hooks(app_name=None)) | |||||
else: | |||||
return _dict(cache().get_value("app_hooks", load_app_hooks)) | |||||
def setup_module_map(): | def setup_module_map(): | ||||
_cache = cache() | _cache = cache() | ||||
@@ -464,7 +469,8 @@ def setup_module_map(): | |||||
def get_file_items(path): | def get_file_items(path): | ||||
if os.path.exists(path): | if os.path.exists(path): | ||||
with open(path, "r") as f: | with open(path, "r") as f: | ||||
return [p.strip() for p in f.read().split("\n") if p.strip() and not p.startswith("#")] | |||||
content = unicode(f.read(), encoding="utf-8") | |||||
return [p.strip() for p in content.splitlines() if p.strip() and not p.startswith("#")] | |||||
else: | else: | ||||
return [] | return [] | ||||
@@ -55,8 +55,7 @@ class HTTPRequest: | |||||
def set_lang(self, lang): | def set_lang(self, lang): | ||||
import translate | import translate | ||||
lang_list = translate.get_lang_dict() | |||||
lang_list = lang_list and lang_list.values() or [] | |||||
lang_list = translate.get_all_languages() or [] | |||||
if not lang: | if not lang: | ||||
return | return | ||||
@@ -88,12 +88,7 @@ def load_translations(bootinfo): | |||||
webnotes.set_user_lang(webnotes.session.user) | webnotes.set_user_lang(webnotes.session.user) | ||||
if webnotes.lang != 'en': | if webnotes.lang != 'en': | ||||
from webnotes.translate import get_lang_data | |||||
from webnotes.utils import get_path | |||||
# framework | |||||
bootinfo["__messages"] = get_lang_data(get_path("lib","public", "js", "wn"), None, "js") | |||||
# doctype and module names | |||||
bootinfo["__messages"].update(get_lang_data(get_path("app","public", "js"), None, "js")) | |||||
bootinfo["__messages"] = webnotes.get_lang_dict("include") | |||||
bootinfo["lang"] = webnotes.lang | bootinfo["lang"] = webnotes.lang | ||||
def get_fullnames(): | def get_fullnames(): | ||||
@@ -15,7 +15,6 @@ def bundle(no_compress): | |||||
"""concat / minify js files""" | """concat / minify js files""" | ||||
# build js files | # build js files | ||||
make_site_public_dirs() | make_site_public_dirs() | ||||
check_lang() | |||||
build(no_compress) | build(no_compress) | ||||
def watch(no_compress): | def watch(no_compress): | ||||
@@ -55,11 +54,7 @@ def make_site_public_dirs(): | |||||
if not os.path.exists(site_public_assets): | if not os.path.exists(site_public_assets): | ||||
os.symlink(os.path.abspath(assets_path), site_public_assets) | os.symlink(os.path.abspath(assets_path), site_public_assets) | ||||
def check_lang(): | |||||
from webnotes.translate import update_translations | |||||
update_translations() | |||||
def clear_pyc_files(): | def clear_pyc_files(): | ||||
from webnotes.utils import get_base_path | from webnotes.utils import get_base_path | ||||
for path, folders, files in os.walk(get_base_path()): | for path, folders, files in os.walk(get_base_path()): | ||||
@@ -193,19 +193,12 @@ def setup_utilities(parser): | |||||
def setup_translation(parser): | def setup_translation(parser): | ||||
parser.add_argument("--build_message_files", default=False, action="store_true", | parser.add_argument("--build_message_files", default=False, action="store_true", | ||||
help="Build message files for translation") | |||||
parser.add_argument("--export_messages", nargs=2, metavar=("LANG-CODE", "FILENAME"), | |||||
help="""Export all messages for a language to translation in a csv file. | |||||
Example, lib/wnf.py --export_messages hi hindi.csv""") | |||||
parser.add_argument("--import_messages", nargs=2, metavar=("LANG-CODE", "FILENAME"), | |||||
help="""Import messages for a language and make language files. | |||||
Example, lib/wnf.py --import_messages hi hindi.csv""") | |||||
parser.add_argument("--google_translate", nargs=3, | |||||
metavar=("LANG-CODE", "INFILE", "OUTFILE"), | |||||
help="Auto translate using Google Translate API") | |||||
parser.add_argument("--translate", nargs=1, metavar="LANG-CODE", | |||||
help="""Rebuild translation for the given langauge and | |||||
use Google Translate to tranlate untranslated messages. use "all" """) | |||||
help="Build message files for translation.") | |||||
parser.add_argument("--get_untranslated", nargs=2, metavar=("LANG-CODE", "TARGET-FILE-PATH"), | |||||
help="""Get untranslated strings for lang.""") | |||||
parser.add_argument("--update_translations", nargs=3, | |||||
metavar=("LANG-CODE", "UNTRANSLATED-FILE-PATH", "TRANSLATED-FILE-PATH"), | |||||
help="""Update translated strings.""") | |||||
# methods | # methods | ||||
@@ -493,35 +486,21 @@ def import_doclist(path, force=False): | |||||
def build_message_files(): | def build_message_files(): | ||||
import webnotes.translate | import webnotes.translate | ||||
webnotes.connect() | webnotes.connect() | ||||
webnotes.translate.build_message_files() | |||||
webnotes.translate.rebuild_all_translation_files() | |||||
webnotes.destroy() | webnotes.destroy() | ||||
@cmd | @cmd | ||||
def export_messages(lang, outfile): | |||||
def get_untranslated(lang, untranslated_file): | |||||
import webnotes.translate | import webnotes.translate | ||||
webnotes.connect() | webnotes.connect() | ||||
webnotes.translate.export_messages(lang, outfile) | |||||
webnotes.translate.get_untranslated(lang, untranslated_file) | |||||
webnotes.destroy() | webnotes.destroy() | ||||
@cmd | @cmd | ||||
def import_messages(lang, infile): | |||||
def update_translations(lang, untranslated_file, translated_file): | |||||
import webnotes.translate | import webnotes.translate | ||||
webnotes.connect() | webnotes.connect() | ||||
webnotes.translate.import_messages(lang, infile) | |||||
webnotes.destroy() | |||||
@cmd | |||||
def google_translate(lang, infile, outfile): | |||||
import webnotes.translate | |||||
webnotes.connect() | |||||
webnotes.translate.google_translate(lang, infile, outfile) | |||||
webnotes.destroy() | |||||
@cmd | |||||
def translate(lang): | |||||
import webnotes.translate | |||||
webnotes.connect() | |||||
webnotes.translate.translate(lang) | |||||
webnotes.translate.update_translations(lang, untranslated_file, translated_file) | |||||
webnotes.destroy() | webnotes.destroy() | ||||
# git | # git | ||||
@@ -37,7 +37,6 @@ def send_event_digest(): | |||||
if events: | if events: | ||||
text = "" | text = "" | ||||
webnotes.set_user_lang(user.name, user.language) | webnotes.set_user_lang(user.name, user.language) | ||||
webnotes.load_translations("core", "doctype", "event") | |||||
text = "<h3>" + webnotes._("Events In Today's Calendar") + "</h3>" | text = "<h3>" + webnotes._("Events In Today's Calendar") + "</h3>" | ||||
for e in events: | for e in events: | ||||
@@ -85,5 +85,5 @@ class DocType: | |||||
self.doc.content = f.read() | self.doc.content = f.read() | ||||
if webnotes.lang != 'en': | if webnotes.lang != 'en': | ||||
from webnotes.translate import update_lang_js | |||||
self.doc.script = update_lang_js(self.doc.script, path) | |||||
from webnotes.translate import get_lang_js | |||||
self.doc.script += get_lang_js("page", self.doc.name) |
@@ -0,0 +1 @@ | |||||
wn._("Test") // for test case |
@@ -3,6 +3,7 @@ | |||||
from __future__ import unicode_literals | from __future__ import unicode_literals | ||||
import webnotes | import webnotes | ||||
from webnotes import _ | |||||
from webnotes.widgets.reportview import execute as runreport | from webnotes.widgets.reportview import execute as runreport | ||||
from webnotes.utils import getdate | from webnotes.utils import getdate | ||||
@@ -16,8 +17,9 @@ def execute(filters=None): | |||||
todo_list.sort(key=lambda todo: (priority_map.get(todo.priority, 0), | todo_list.sort(key=lambda todo: (priority_map.get(todo.priority, 0), | ||||
todo.date and getdate(todo.date) or getdate("1900-01-01")), reverse=True) | todo.date and getdate(todo.date) or getdate("1900-01-01")), reverse=True) | ||||
columns = ["ID:Link/ToDo:90", "Priority::60", "Date:Date", "Description::150", | |||||
"Assigned To/Owner:Link/Profile:120", "Assigned By:Link/Profile:120", "Reference::200"] | |||||
columns = [_("ID")+":Link/ToDo:90", _("Priority")+"::60", _("Date")+ ":Date", | |||||
_("Description")+"::150", _("Assigned To/Owner") + ":Link/Profile:120", | |||||
_("Assigned By")+":Link/Profile:120", _("Reference")+"::200"] | |||||
result = [] | result = [] | ||||
for todo in todo_list: | for todo in todo_list: | ||||
@@ -337,30 +337,7 @@ def add_search_fields(doclist): | |||||
def update_language(doclist): | def update_language(doclist): | ||||
"""update language""" | """update language""" | ||||
if webnotes.lang != 'en': | if webnotes.lang != 'en': | ||||
from webnotes.modules import get_doc_path | |||||
if not hasattr(webnotes.local, 'translations'): | |||||
webnotes.local.translations = {} | |||||
translations = webnotes.local.translations | |||||
# load languages for each doctype | |||||
from webnotes.translate import get_lang_data | |||||
_messages = {} | |||||
for d in doclist: | |||||
if d.doctype=='DocType': | |||||
_messages.update(get_lang_data(get_doc_path(d.module, d.doctype, d.name), | |||||
webnotes.lang, 'doc')) | |||||
_messages.update(get_lang_data(get_doc_path(d.module, d.doctype, d.name), | |||||
webnotes.lang, 'js')) | |||||
doc = doclist[0] | |||||
# attach translations to client | |||||
doc.fields["__messages"] = _messages | |||||
if not webnotes.lang in translations: | |||||
translations[webnotes.lang] = webnotes._dict({}) | |||||
translations[webnotes.lang].update(_messages) | |||||
doclist[0].fields["__messages"] = webnotes.get_lang_dict("doctype", doclist[0].name) | |||||
class DocTypeDocList(webnotes.model.doclist.DocList): | class DocTypeDocList(webnotes.model.doclist.DocList): | ||||
def get_field(self, fieldname, parent=None, parentfield=None): | def get_field(self, fieldname, parent=None, parentfield=None): | ||||
@@ -0,0 +1,62 @@ | |||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors | |||||
# MIT License. See license.txt | |||||
import webnotes, unittest, os | |||||
import webnotes.translate | |||||
class TestTranslations(unittest.TestCase): | |||||
def test_doctype(self, messages=None): | |||||
if not messages: | |||||
messages = webnotes.translate.get_messages_from_doctype("Role") | |||||
self.assertTrue("Role Name" in messages) | |||||
def test_page(self, messages=None): | |||||
if not messages: | |||||
messages = webnotes.translate.get_messages_from_page("finder") | |||||
self.assertTrue("Finder" in messages) | |||||
def test_report(self, messages=None): | |||||
if not messages: | |||||
messages = webnotes.translate.get_messages_from_report("ToDo") | |||||
self.assertTrue("Test" in messages) | |||||
def test_include_js(self, messages=None): | |||||
if not messages: | |||||
messages = webnotes.translate.get_messages_from_include_files("webnotes") | |||||
self.assertTrue("History" in messages) | |||||
def test_server(self, messages=None): | |||||
if not messages: | |||||
messages = webnotes.translate.get_server_messages("webnotes") | |||||
self.assertTrue("Login" in messages) | |||||
self.assertTrue("Did not save" in messages) | |||||
def test_all_app(self): | |||||
messages = webnotes.translate.get_messages_for_app("webnotes") | |||||
self.test_doctype(messages) | |||||
self.test_page(messages) | |||||
self.test_report(messages) | |||||
self.test_include_js(messages) | |||||
self.test_server(messages) | |||||
def test_load_translations(self): | |||||
webnotes.translate.clear_cache() | |||||
self.assertFalse(webnotes.cache().get_value("lang:de")) | |||||
langdict = webnotes.translate.get_full_dict("de") | |||||
self.assertEquals(langdict['Row'], 'Reihe') | |||||
def test_write_csv(self): | |||||
tpath = webnotes.get_pymodule_path("webnotes", "translations", "de.csv") | |||||
os.remove(tpath) | |||||
webnotes.translate.write_translations_file("webnotes", "de") | |||||
self.assertTrue(os.path.exists(tpath)) | |||||
self.assertEquals(dict(webnotes.translate.read_csv_file(tpath)).get("Row"), "Reihe") | |||||
def test_get_dict(self): | |||||
webnotes.local.lang = "de" | |||||
self.assertEquals(webnotes.get_lang_dict("doctype", "Role").get("Role"), "Rolle") | |||||
if __name__=="__main__": | |||||
webnotes.connect("site1") | |||||
unittest.main() |
@@ -66,7 +66,7 @@ def add_website_sitemap_config(page_or_generator, app, path, fname, basepath): | |||||
"link_name": name, | "link_name": name, | ||||
"template_path": os.path.relpath(os.path.join(path, fname), basepath), | "template_path": os.path.relpath(os.path.join(path, fname), basepath), | ||||
}) | }) | ||||
controller_name = fname.split(".")[0].replace("-", "_") + ".py" | controller_name = fname.split(".")[0].replace("-", "_") + ".py" | ||||
controller_path = os.path.join(path, controller_name) | controller_path = os.path.join(path, controller_name) | ||||
if os.path.exists(controller_path): | if os.path.exists(controller_path): | ||||
@@ -19,7 +19,7 @@ | |||||
</style> | </style> | ||||
{% endblock %} | {% endblock %} | ||||
{% set title="Login" %} | |||||
{% set title=_("Login") %} | |||||
{% block content %} | {% block content %} | ||||
@@ -32,7 +32,7 @@ | |||||
<div class="col-sm-offset-1 col-sm-10"> | <div class="col-sm-offset-1 col-sm-10"> | ||||
<div class="panel panel-default"> | <div class="panel panel-default"> | ||||
<div class="panel-heading"> | <div class="panel-heading"> | ||||
<h4><i class="icon-lock"></i> Login</h4> | |||||
<h4><i class="icon-lock"></i> {{ _("Login") }}</h4> | |||||
</div> | </div> | ||||
<div class="panel-body row" style="padding: 30px"> | <div class="panel-body row" style="padding: 30px"> | ||||
<div class="col-sm-6 login-wrapper"> | <div class="col-sm-6 login-wrapper"> | ||||
@@ -52,7 +52,7 @@ | |||||
</div> | </div> | ||||
<div class="form-group"> | <div class="form-group"> | ||||
<button type="submit" id="login_btn" | <button type="submit" id="login_btn" | ||||
class="btn btn-primary">Login</button> | |||||
class="btn btn-primary">{{ _("Login") }}</button> | |||||
<img src="images/ui/button-load.gif" id="login-spinner" style="display: none;"> | <img src="images/ui/button-load.gif" id="login-spinner" style="display: none;"> | ||||
</div> | </div> | ||||
<p id="forgot-link"></p> | <p id="forgot-link"></p> | ||||
@@ -108,6 +108,7 @@ def build_page(page_name): | |||||
context["base_template"] = jenv.get_template("portal/templates/base.html") | context["base_template"] = jenv.get_template("portal/templates/base.html") | ||||
template_name = page_options['template_path'] | template_name = page_options['template_path'] | ||||
context["_"] = webnotes._ | |||||
html = jenv.get_template(template_name).render(context) | html = jenv.get_template(template_name).render(context) | ||||
if not no_cache: | if not no_cache: | ||||
@@ -26,13 +26,8 @@ def getpage(): | |||||
if has_permission(doclist): | if has_permission(doclist): | ||||
# load translations | # load translations | ||||
if webnotes.lang != "en": | if webnotes.lang != "en": | ||||
from webnotes.modules import get_doc_path | |||||
from webnotes.translate import get_lang_data | |||||
d = doclist[0] | |||||
messages = get_lang_data(get_doc_path(d.module, d.doctype, d.name), | |||||
webnotes.lang, 'js') | |||||
webnotes.response["__messages"] = messages | |||||
webnotes.response["__messages"] = webnotes.get_lang_dict("page", d.name) | |||||
webnotes.response['docs'] = doclist | webnotes.response['docs'] = doclist | ||||
else: | else: | ||||
webnotes.response['403'] = 1 | webnotes.response['403'] = 1 | ||||
@@ -34,10 +34,7 @@ def get_script(report_name): | |||||
# load translations | # load translations | ||||
if webnotes.lang != "en": | if webnotes.lang != "en": | ||||
from webnotes.translate import get_lang_data | |||||
if os.path.exists(report_folder): | |||||
messages = get_lang_data(report_folder, webnotes.lang, 'js') | |||||
webnotes.response["__messages"] = messages | |||||
webnotes.response["__messages"] = webnotes.get_lang_dict("report", report_name) | |||||
return script | return script | ||||