Export strings based on a module-folder base

I am working on a tranlation to danish.

I have been reading Not Found and have bootstrapped for at new language.

bench frappe --get_untranslated [lang] [path]

However the file is over 5000 lines and seems totally unordered to me.

I have been looking at at the translate.py under frappe-bench/apps/frappe/frappe to possible modify it to accept som kind on delimiter on the export.

def get_untranslated(lang, untranslated_file, get_all=False):
	"""translate objects using Google API. Add you own API key for translation"""
	apps = frappe.get_all_apps(True)

	messages = []
	untranslated = []
	for app in apps:

	messages = list(set(messages))

	def escape_newlines(s):
		return (s.replace("\\\n", "|||||")
				.replace("\\n", "||||")
				.replace("\n", "|||"))

	if get_all:
		print str(len(messages)) + " messages"
		with open(untranslated_file, "w") as f:
			for m in messages:
				# replace \n with ||| so that internal linebreaks don't get split
				f.write((escape_newlines(m) + os.linesep).encode("utf-8"))
		full_dict = get_full_dict(lang)

		for m in messages:
			if not full_dict.get(m):

		if untranslated:
			print str(len(untranslated)) + " missing translations of " + str(len(messages))
			with open(untranslated_file, "w") as f:
				for m in untranslated:
					# replace \n with ||| so that internal linebreaks don't get split
					f.write((escape_newlines(m) + os.linesep).encode("utf-8"))
			print "all translated!"

How can I modify this to accept an extra parameter specifying a specific part of the app?

EDIT: (20150223T1641GMT+1)
instead of exporting everything into a single file - it would be nice if the export created a single file per module

Nice work by the way.


Did not understand the question.

Translations are maintained globally unfortunately - I agree there should be a better way to add context.

Do send a pull-request - will be happy to add your contribution.

What I meant was:

Since every module has a name and separate folder I was looking into a way to have the module specific texts in a single file.

text for contacts-module in contacts-module.txt
text for accounts-module in accounts-module.txt

I have no python-experience though it looks familar but the issue has somewhat downgraded itself.

I am stonewalled on Translation export-Import issue



There is only one big dictionary that gets stored in the cache in run time.

Server side translations don’t need context, so they get translated using the _("text") method.

In the client-side, translations are appended to javascript files on need basis and the string replacement happens in the browser.

I get that. I am not anyway refererring to the runtime :wink: I really don’t care about that section :slight_smile:

AFAIU the –update_translation is somewhat agnostic as long as it has the original file to compare against.

The primary goal was having the –get_untranslated function allowing for a more translation friendly environment by creating one file per module.

See - this makes the task more approachable since one can translate smaller portions of the overall interface - instead of getting stuck with the nasty machine translation.

This would make the task much more managable and a lot easier to troubleshoot - hence the stonewalling issue.

You should try the translator


It has a nice search function now @pdvyas

I know - even though - the task of translating 5000+ lines, seemingly appearing in random order - that really gets to you.

By the way - the da-DK lang does not exist.

But would it be such a huge change?


  • the function is writing one single file outside the app/module loop

change to

  • the function write a file inside the module loop (ideally composing the input-filename with the module-name) before shifting to next module

As mentioned - I have no experience in python - also I do not have the deep understanding you have of the –get_untranslated function.

AFAIS the change would be minor - if having the deep knowledge of the python modules.

Obviously I have no such knowledge.

I would have to spend hours searching through your modules to get an idea of how you accomplish this task.

Then I might be able to clash some code but that would not be optimal to accomplish a change that you could implement in what? 30 minutes? because you know exactly where to inject the new code.

I see two ways,

  • We add it to the translator now and you can edit online (but I guess, you want to go module wise)
  • [version 5] On your local, add the language to frappe/data/languages.txt and run bench frappe --rebuild_translations, this should generate the da-DK.csv with three columns, Position, Source and Translated (would be empty). You can then sort by position on first column in your spreadsheet program, they will appear almost module wise.

It loops over modules here, https://github.com/frappe/frappe/blob/v5.0/frappe/translate.py#L199
declare modules = ['the single module you want'] just above it and export for a limited subset


I have managed to get a rough translation rolling - YES !

Also created pull-requests on github



Hey, for technical reasons of versioning we can only merge translations via file once. After that, when it hits the translator portal, we cannot merge csv as there’s no way to know if a string was corrected or not. So, you can send a pull request after you’re done with a sizable amount of strings, then we add it translator. Is that fine?

I see - I think we should discard the pull request for now.

I have 2 thing to consider:

Going the module wayon v4

Or switch to v5 and do the translating there.