No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 
 
 
 

292 líneas
8.6 KiB

  1. # Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
  2. # MIT License. See license.txt
  3. from __future__ import unicode_literals
  4. """
  5. Contributing:
  6. 1. Add the .csv file
  7. 2. Run import
  8. 3. Then run translate
  9. """
  10. # loading
  11. # doctype, page, report
  12. # boot(startup)
  13. # wn.require
  14. # webnotes._
  15. import webnotes, os, re, codecs, json
  16. def get_user_lang(user=None):
  17. if not user:
  18. user = webnotes.session.user
  19. return get_lang_dict().get(webnotes.conn.get_value("Profile", user, "language") or "english")
  20. def get_all_languages():
  21. return [a.split()[0] for a in get_lang_info()]
  22. def get_lang_dict():
  23. return dict([[a[1], a[0]] for a in [a.split() for a in get_lang_info()]])
  24. def get_lang_info():
  25. return webnotes.cache().get_value("langinfo",
  26. lambda:webnotes.get_file_items(os.path.join(webnotes.local.sites_path, "languages.txt")))
  27. def rebuild_all_translation_files():
  28. for lang in get_all_languages():
  29. for app in get_all_apps():
  30. write_translations_file(app, lang)
  31. def write_translations_file(app, lang, full_dict=None):
  32. tpath = webnotes.get_pymodule_path(app, "translations")
  33. webnotes.create_folder(tpath)
  34. write_csv_file(os.path.join(tpath, lang + ".csv"),
  35. get_messages_for_app(app), full_dict or get_full_dict(lang))
  36. def get_dict(fortype, name=None):
  37. fortype = fortype.lower()
  38. cache = webnotes.cache()
  39. cache_key = "translation_assets:" + webnotes.local.lang
  40. asset_key = fortype + ":" + (name or "-")
  41. translation_assets = cache.get_value(cache_key) or {}
  42. if not asset_key in translation_assets:
  43. if fortype=="doctype":
  44. messages = get_messages_from_doctype(name)
  45. elif fortype=="page":
  46. messages = get_messages_from_page(name)
  47. elif fortype=="report":
  48. messages = get_messages_from_report(name)
  49. elif fortype=="include":
  50. messages = get_messages_from_include_files()
  51. elif fortype=="jsfile":
  52. messages = get_messages_from_file(name)
  53. translation_assets[asset_key] = make_dict_from_messages(messages)
  54. cache.set_value(cache_key, translation_assets)
  55. return translation_assets[asset_key]
  56. def add_lang_dict(code):
  57. messages = extract_messages_from_code(code)
  58. code += "\n\n$.extend(wn._messages, %s)" % json.dumps(make_dict_from_messages(messages))
  59. return code
  60. def make_dict_from_messages(messages, full_dict=None):
  61. out = {}
  62. if full_dict==None:
  63. full_dict = get_full_dict(webnotes.local.lang)
  64. for m in messages:
  65. if m in full_dict:
  66. out[m] = full_dict[m]
  67. return out
  68. def get_lang_js(fortype, name):
  69. return "\n\n$.extend(wn._messages, %s)" % json.dumps(get_dict(fortype, name))
  70. def get_full_dict(lang):
  71. if lang == "en": return {}
  72. return webnotes.cache().get_value("lang:" + lang, lambda:load_lang(lang))
  73. def load_lang(lang, apps=None):
  74. out = {}
  75. for app in (apps or webnotes.get_all_apps(True)):
  76. path = os.path.join(webnotes.get_pymodule_path(app), "translations", lang + ".csv")
  77. if os.path.exists(path):
  78. cleaned = dict([item for item in dict(read_csv_file(path)).iteritems() if item[1]])
  79. out.update(cleaned)
  80. return out
  81. def clear_cache():
  82. cache = webnotes.cache()
  83. cache.delete_value("langinfo")
  84. for lang in get_all_languages():
  85. cache.delete_value("lang:" + lang)
  86. cache.delete_value("translation_assets:" + lang)
  87. def get_messages_for_app(app):
  88. messages = []
  89. modules = ", ".join(['"{}"'.format(m.title().replace("_", " ")) \
  90. for m in webnotes.local.app_modules[app]])
  91. # doctypes
  92. for name in webnotes.conn.sql_list("""select name from tabDocType
  93. where module in ({})""".format(modules)):
  94. messages.extend(get_messages_from_doctype(name))
  95. # pages
  96. for name in webnotes.conn.sql_list("""select name from tabPage
  97. where module in ({})""".format(modules)):
  98. messages.extend(get_messages_from_page(name))
  99. # reports
  100. for name in webnotes.conn.sql_list("""select tabReport.name from tabDocType, tabReport
  101. where tabReport.ref_doctype = tabDocType.name
  102. and tabDocType.module in ({})""".format(modules)):
  103. messages.extend(get_messages_from_report(name))
  104. # app_include_files
  105. messages.extend(get_messages_from_include_files(app))
  106. # server_messages
  107. messages.extend(get_server_messages(app))
  108. return list(set(messages))
  109. def get_messages_from_doctype(name):
  110. messages = []
  111. meta = webnotes.get_doctype(name)
  112. messages = [meta[0].name, meta[0].description, meta[0].module]
  113. for d in meta.get({"doctype":"DocField"}):
  114. messages.extend([d.label, d.description])
  115. if d.fieldtype=='Select' and d.options \
  116. and not d.options.startswith("link:") \
  117. and not d.options.startswith("attach_files:"):
  118. options = d.options.split('\n')
  119. if not "icon" in options[0]:
  120. messages.extend(options)
  121. # extract from js, py files
  122. doctype_file_path = webnotes.get_module_path(meta[0].module, "doctype", meta[0].name, meta[0].name)
  123. messages.extend(get_messages_from_file(doctype_file_path + ".js"))
  124. return clean(messages)
  125. def get_messages_from_page(name):
  126. return get_messages_from_page_or_report("Page", name)
  127. def get_messages_from_report(name):
  128. report = webnotes.doc("Report", name)
  129. messages = get_messages_from_page_or_report("Report", name,
  130. webnotes.conn.get_value("DocType", report.ref_doctype, "module"))
  131. if report.query:
  132. messages.extend(re.findall('"([^:,^"]*):', report.query))
  133. messages.append(report.report_name)
  134. return clean(messages)
  135. def get_messages_from_page_or_report(doctype, name, module=None):
  136. if not module:
  137. module = webnotes.conn.get_value(doctype, name, "module")
  138. file_path = webnotes.get_module_path(module, doctype, name, name)
  139. messages = get_messages_from_file(file_path + ".js")
  140. return clean(messages)
  141. def get_server_messages(app):
  142. messages = []
  143. for basepath, folders, files in os.walk(webnotes.get_pymodule_path(app)):
  144. for dontwalk in (".git", "public", "locale"):
  145. if dontwalk in folders: folders.remove(dontwalk)
  146. for f in files:
  147. if f.endswith(".py") or f.endswith(".html"):
  148. messages.extend(get_messages_from_file(os.path.join(basepath, f)))
  149. return clean(messages)
  150. def get_messages_from_include_files(app_name=None):
  151. messages = []
  152. hooks = webnotes.get_hooks(app_name)
  153. for file in (hooks.app_include_js or []) + (hooks.web_include_js or []):
  154. messages.extend(get_messages_from_file(os.path.join(webnotes.local.sites_path, file)))
  155. return messages
  156. def get_messages_from_file(path):
  157. """get list of messages from a code file"""
  158. if os.path.exists(path):
  159. with open(path, 'r') as sourcefile:
  160. return extract_messages_from_code(sourcefile.read(), path.endswith(".py"))
  161. else:
  162. return []
  163. def extract_messages_from_code(code, is_py=False):
  164. messages = []
  165. messages += re.findall('_\("([^"]*)"\)', code)
  166. messages += re.findall("_\('([^']*)'\)", code)
  167. if is_py:
  168. messages += re.findall('_\("{3}([^"]*)"{3}.*\)', code, re.S)
  169. return messages
  170. def clean(messages):
  171. return filter(lambda t: t if t else None, list(set(messages)))
  172. def read_csv_file(path):
  173. from csv import reader
  174. with codecs.open(path, 'r', 'utf-8') as msgfile:
  175. data = msgfile.read()
  176. data = reader([r.encode('utf-8') for r in data.splitlines()])
  177. newdata = [[unicode(val, 'utf-8') for val in row] for row in data]
  178. return newdata
  179. def write_csv_file(path, app_messages, lang_dict):
  180. app_messages.sort()
  181. from csv import writer
  182. with open(path, 'w') as msgfile:
  183. w = writer(msgfile)
  184. for m in app_messages:
  185. w.writerow([m.encode('utf-8'), lang_dict.get(m, '').encode('utf-8')])
  186. def get_untranslated(lang, untranslated_file):
  187. """translate objects using Google API. Add you own API key for translation"""
  188. clear_cache()
  189. apps = webnotes.get_all_apps(True)
  190. messages = []
  191. untranslated = []
  192. for app in apps:
  193. messages.extend(get_messages_for_app(app))
  194. full_dict = get_full_dict(lang)
  195. for m in messages:
  196. if not full_dict.get(m):
  197. untranslated.append(m)
  198. if untranslated:
  199. print str(len(untranslated)) + " missing translations of " + str(len(messages))
  200. with open(untranslated_file, "w") as f:
  201. f.write("\n".join(untranslated))
  202. else:
  203. print "all translated!"
  204. def update_translations(lang, untranslated_file, translated_file):
  205. clear_cache()
  206. full_dict = get_full_dict(lang)
  207. full_dict.update(dict(zip(webnotes.get_file_items(untranslated_file),
  208. webnotes.get_file_items(translated_file))))
  209. for app in webnotes.get_all_apps(True):
  210. write_translations_file(app, lang, full_dict)
  211. def google_translate(lang, untranslated):
  212. import requests
  213. if untranslated:
  214. response = requests.get("""https://www.googleapis.com/language/translate/v2""",
  215. params = {
  216. "key": webnotes.conf.google_api_key,
  217. "source": "en",
  218. "target": lang,
  219. "q": "\n".join(untranslated)
  220. })
  221. data = response.json()
  222. if "error" in data:
  223. print data
  224. translated = data["data"]["translations"][0]["translatedText"]
  225. if translated:
  226. return dict(zip(untranslated, translated))
  227. else:
  228. print "unable to translate"
  229. return {}