def _get_next_goal_count(self): # Putting the next import at the top of the file causes circular # import issues. from pootle_tagging.models import Goal goal = Goal.get_most_important_incomplete_for_path(self.directory) if goal is not None: return goal.get_incomplete_words_in_path(self.directory) return 0
def get_next_goal_count(self): # Putting the next import at the top of the file causes circular # import issues. from pootle_tagging.models import Goal goal = Goal.get_most_important_incomplete_for_path(self.directory) if goal is not None: return goal.get_incomplete_words_in_path(self.directory) return 0
def get_next_goal_url(self): # Putting the next import at the top of the file causes circular # import issues. from pootle_tagging.models import Goal goal = Goal.get_most_important_incomplete_for_path(self.directory) if goal is not None: return goal.get_translate_url_for_path(self.directory.pootle_path, state='incomplete') return ''
def get_next_goal_url(self): # Trigger only if it is a regular directory inside a TP. if self.pootle_path.count('/') > 3: # Putting the next import at the top of the file causes circular # import issues. from pootle_tagging.models import Goal goal = Goal.get_most_important_incomplete_for_path(self) if goal is not None: return goal.get_translate_url_for_path(self.pootle_path, state='incomplete') return ''
def get_translate_actions(path_obj): """Return a list of translation action links to be displayed for each ``path_obj``.""" goals_summary = [] # Build URL for getting more summary information for the current path. url_path_summary_more = reverse('pootle-xhr-summary-more') if path_obj.is_dir: # Putting the next import at the top of the file causes circular # import issues. from pootle_tagging.models import Goal pootle_path = path_obj.pootle_path goal = Goal.get_most_important_incomplete_for_path(path_obj) if goal is not None: goal_words = goal.get_incomplete_words_in_path(path_obj) goal_url = goal.get_translate_url_for_path(pootle_path, state='incomplete') if goal_words > 0: goals_summary.extend([ u'<br /><a class="continue-translation" href="%(url)s">' % { 'url': goal_url, }, ungettext(u'<span class="caption">Next most important ' u'goal:</span> <span class="counter">%(num)d ' u'word left</span>', u'<span class="caption">Next most important ' u'goal:</span> <span class="counter">%(num)d ' u'words left</span>', goal_words, {'num': goal_words, }), ]) return {'is_dir': path_obj.is_dir, 'goals_summary': u''.join(goals_summary), 'summary_more_url': url_path_summary_more, 'translate_url': path_obj.get_translate_url(state='all'), 'incomplete_url': path_obj.get_translate_url(state='incomplete'), 'suggestions_url': path_obj.get_translate_url(state='suggestions'), 'critical_url': path_obj.get_critical_url(), }
def get_translate_actions(path_obj): """Return a list of translation action links to be displayed for each ``path_obj``.""" goals_summary = [] if path_obj.is_dir: # Putting the next import at the top of the file causes circular # import issues. from pootle_tagging.models import Goal pootle_path = path_obj.pootle_path goal = Goal.get_most_important_incomplete_for_path(path_obj) if goal is not None: goal_words = goal.get_incomplete_words_in_path(path_obj) goal_url = goal.get_translate_url_for_path(pootle_path, state='incomplete') if goal_words > 0: goals_summary.extend([ u'<br /><a class="continue-translation" href="%(url)s">' % { 'url': goal_url, }, ungettext( u'<span class="caption">Next most important ' u'goal:</span> <span class="counter">%(num)d ' u'word left</span>', u'<span class="caption">Next most important ' u'goal:</span> <span class="counter">%(num)d ' u'words left</span>', goal_words, { 'num': goal_words, }), ]) return { 'is_dir': path_obj.is_dir, 'goals_summary': u''.join(goals_summary), 'translate_url': path_obj.get_translate_url(state='all'), 'incomplete_url': path_obj.get_translate_url(state='incomplete'), 'suggestions_url': path_obj.get_translate_url(state='suggestions'), 'critical_url': path_obj.get_critical_url(), }
def get_translate_actions(path_obj): """Return a list of translation action links to be displayed for each ``path_obj``.""" goals_summary = [] if path_obj.is_dir: # Putting the next import at the top of the file causes circular # import issues. from pootle_tagging.models import Goal pootle_path = path_obj.pootle_path goal = Goal.get_most_important_incomplete_for_path(path_obj) if goal is not None: goal_words = goal.get_incomplete_words_in_path(path_obj) goal_url = goal.get_translate_url_for_path(pootle_path, state="incomplete") if goal_words > 0: goals_summary.extend( [ u'<br /><a class="continue-translation" href="%(url)s">' % {"url": goal_url}, ungettext( u'<span class="caption">Next most important ' u'goal:</span> <span class="counter">%(num)d ' u"word left</span>", u'<span class="caption">Next most important ' u'goal:</span> <span class="counter">%(num)d ' u"words left</span>", goal_words, {"num": goal_words}, ), ] ) return { "is_dir": path_obj.is_dir, "goals_summary": u"".join(goals_summary), "translate_url": path_obj.get_translate_url(state="all"), "incomplete_url": path_obj.get_translate_url(state="incomplete"), "suggestions_url": path_obj.get_translate_url(state="suggestions"), "critical_url": path_obj.get_critical_url(), }
def get_path_summary(path_obj): """Return a list of sentences to be displayed for each ``path_obj``.""" goals_summary = [] # Build URL for getting more summary information for the current path. url_path_summary_more = reverse('pootle-xhr-summary-more') if path_obj.is_dir: # Putting the next import at the top of the file causes circular # import issues. from pootle_tagging.models import Goal pootle_path = path_obj.pootle_path goal = Goal.get_most_important_incomplete_for_path(path_obj) if goal is not None: goal_words = goal.get_incomplete_words_in_path(path_obj) goal_url = goal.get_translate_url_for_path(pootle_path, state='incomplete') if goal_words > 0: goals_summary.extend([ u'<br /><a class="path-incomplete" href="%(url)s">' % { 'url': goal_url, }, ungettext(u'Next most important goal (%(num)d word left)', u'Next most important goal (%(num)d words left)', goal_words, {'num': goal_words, }), ]) return {'is_dir': path_obj.is_dir, 'goals_summary': u''.join(goals_summary), 'summary_more_url': url_path_summary_more, 'translate_url': path_obj.get_translate_url(state='all'), 'incomplete_url': path_obj.get_translate_url(state='incomplete'), 'suggestions_url': path_obj.get_translate_url(state='suggestions')}
def handle(self, *args, **options): """Add project goals from file to the given project.""" project_name = options.get('project_name', None) goals_filename = options.get('goals_file', None) if project_name is None: raise CommandError("A project must be provided.") elif goals_filename is None: raise CommandError("A filename must be provided.") elif not os.path.isfile(goals_filename): raise CommandError("Filename '%s' doesn't point to an existing " "file." % goals_filename) try: project = Project.objects.get(code=project_name) except Project.DoesNotExist: raise CommandError("Project '%s' does not exist." % project_name) template_tp = project.get_template_translationproject() if not template_tp: raise CommandError("Project '%s' doesn't have a template " "translation project." % project_name) try: inputfile = open(goals_filename, "r") inputlines = inputfile.readlines() inputfile.close() except IOError as e: raise CommandError("Some error occurred while handling the file: " "%s" % e.strerror) line_number = 0 goals_dict = {} template_language = template_tp.language.code for line in inputlines: line_number += 1 line.strip() try: goal_name, filename = line.split("\t") except ValueError: raise CommandError("Wrong syntax at line %d." % line_number) # Polish the goal name and filename before working with them. filename = filename.strip().lstrip("./") filename = "/".join([project_name, template_language, filename]) goal_name = goal_name.lower() if not goal_name.startswith("goal:"): goal_name = "goal:" + goal_name try: goals_dict[goal_name].append(filename) except KeyError: goals_dict[goal_name] = [filename] logging.info("\nParsed %d lines from '%s'\n", line_number, goals_filename) # First check if any of the goals already exists and it is not a # project goal, in order to abort before creating or adding any of the # goals to the files. for goal_name in goals_dict.keys(): try: goal = Goal.objects.get(name=goal_name) if not goal.project_goal: raise CommandError("The goal '%s' already exists but it " "isn't a project goal." % goal) except Goal.DoesNotExist: pass # Criteria to get all the items in a random goal that correspond to # stores in the 'templates' translation project. # # It is used several lines below, but here is possible to calculate it # just once. stores_criteria = { 'content_type': ContentType.objects.get_for_model(Store), 'object_id__in': template_tp.stores.values_list('pk', flat=True), } applied_goals = set() # Now apply the goal to each of the stores. for goal_name in goals_dict.keys(): try: # Retrieve the goal if it already exists. goal = Goal.objects.get(name=goal_name) # Unapply the goal from all the stores in the 'templates' # translation project to which the goal is currently applied. goal.items_with_goal.filter(**stores_criteria).delete() except Goal.DoesNotExist: # If the goal doesn't exist yet then create it. criteria = { 'name': goal_name, # Note: for some unknown reason it is necessary to provide # the slug instead of letting the model create it. 'slug': slugify_tag_name(goal_name), 'project_goal': True, } try: # Get the goal priority from the end of the goal name. criteria['priority'] = int(goal_name[-1]) except ValueError: pass goal = Goal(**criteria) goal.save() for filename in goals_dict[goal_name]: try: store = template_tp.stores.get(file=filename) store.goals.add(goal) applied_goals.add(goal_name) logging.info("Goal '%s' applied to '%s'.", goal_name, filename) except ObjectDoesNotExist: logging.warning( "File '%s' is not on the template " "language. Skipping it.\n", filename) logging.info("\nSucessfully added %d project goals to project '%s'.", len(applied_goals), project_name)
def overview(request, translation_project, dir_path, filename=None, goal=None, in_goal_overview=False): current_path = translation_project.directory.pootle_path + dir_path if filename: current_path = current_path + filename store = get_object_or_404(Store, pootle_path=current_path) directory = store.parent ctx = { 'store_tags': store.tag_like_objects, } template_name = "translation_projects/store_overview.html" else: store = None directory = get_object_or_404(Directory, pootle_path=current_path) ctx = { 'tp_tags': translation_project.tag_like_objects, } template_name = "translation_projects/overview.html" if (check_permission('translate', request) or check_permission('suggest', request) or check_permission('overwrite', request)): ctx.update({ 'upload_form': _handle_upload_form(request, current_path, translation_project, directory), }) can_edit = check_permission('administrate', request) project = translation_project.project language = translation_project.language path_obj = store or directory #TODO enable again some actions when drilling down a goal. if goal is None: actions = action_groups(request, path_obj) else: actions = [] action_output = '' running = request.GET.get(EXTDIR, '') #TODO enable the following again when drilling down a goal. if running and goal is None: if store: act = StoreAction else: act = TranslationProjectAction try: action = act.lookup(running) except KeyError: messages.error( request, _("Unable to find '%(action)s' in '%(extdir)s'") % { 'action': act, 'extdir': running }) else: if not getattr(action, 'nosync', False): (store or translation_project).sync() if action.is_active(request): vcs_dir = settings.VCS_DIRECTORY po_dir = settings.PODIRECTORY tp_dir = directory.get_real_path() store_fn = '*' if store: tp_dir_slash = add_trailing_slash(tp_dir) if store.file.name.startswith(tp_dir_slash): # Note: store_f used below in reverse() call. store_f = store.file.name[len(tp_dir_slash):] store_fn = store_f.replace('/', os.sep) # Clear possibly stale output/error (even from other path_obj). action.set_output('') action.set_error('') try: action.run(path=path_obj, root=po_dir, tpdir=tp_dir, project=project.code, language=language.code, store=store_fn, style=translation_project.file_style, vc_root=vcs_dir) except StandardError: err = (_("Error while running '%s' extension action") % action.title) logging.exception(err) if (action.error): messages.error(request, action.error) else: messages.error(request, err) else: if (action.error): messages.warning(request, action.error) action_output = action.output if getattr(action, 'get_download', None): export_path = action.get_download(path_obj) if export_path: import mimetypes abs_path = absolute_real_path(export_path) filename = os.path.basename(export_path) mimetype, encoding = mimetypes.guess_type(filename) mimetype = mimetype or 'application/octet-stream' with open(abs_path, 'rb') as f: response = HttpResponse(f.read(), mimetype=mimetype) response['Content-Disposition'] = ( 'attachment; filename="%s"' % filename) return response if not action_output: if not store: rev_args = [language.code, project.code, ''] overview_url = reverse('pootle-tp-overview', args=rev_args) else: slash = store_f.rfind('/') store_d = '' if slash > 0: store_d = store_f[:slash] store_f = store_f[slash + 1:] elif slash == 0: store_f = store_f[1:] rev_args = [ language.code, project.code, store_d, store_f ] overview_url = reverse('pootle-tp-overview', args=rev_args) return HttpResponseRedirect(overview_url) if goal is None: description = translation_project.description else: description = goal.description ctx.update({ 'resource_obj': request.resource_obj, 'translation_project': translation_project, 'description': description, 'project': project, 'language': language, 'path_obj': path_obj, 'resource_path': request.resource_path, 'topstats': gentopstats_translation_project(translation_project), 'feed_path': directory.pootle_path[1:], 'action_groups': actions, 'action_output': action_output, 'can_edit': can_edit, }) tp_pootle_path = translation_project.pootle_path if store is None: path_obj_goals = Goal.get_goals_for_path(path_obj.pootle_path) path_obj_has_goals = len(path_obj_goals) > 0 if in_goal_overview and path_obj_has_goals: # Then show the goals tab. table_fields = [ 'name', 'progress', 'priority', 'total', 'need-translation', 'suggestions' ] items = [ make_goal_item(path_obj_goal, path_obj.pootle_path) for path_obj_goal in path_obj_goals ] ctx.update({ 'table': { 'id': 'tp-goals', 'proportional': False, 'fields': table_fields, 'headings': get_table_headings(table_fields), 'parent': get_parent(directory), 'items': items, }, 'path_obj_has_goals': True, }) elif goal in path_obj_goals: # Then show the drill down view for the specified goal. table_fields = [ 'name', 'progress', 'total', 'need-translation', 'suggestions' ] ctx.update({ 'table': { 'id': 'tp-goals', 'proportional': True, 'fields': table_fields, 'headings': get_table_headings(table_fields), 'parent': get_goal_parent(directory, goal), 'items': get_goal_children(directory, goal), }, 'goal': goal, 'goal_url': goal.get_drill_down_url_for_path(tp_pootle_path), 'path_obj_has_goals': True, }) else: # Then show the files tab. table_fields = [ 'name', 'progress', 'total', 'need-translation', 'suggestions' ] ctx.update({ 'table': { 'id': 'tp-files', 'proportional': True, 'fields': table_fields, 'headings': get_table_headings(table_fields), 'parent': get_parent(directory), 'items': get_children(directory), }, 'path_obj_has_goals': path_obj_has_goals, }) elif goal is not None: ctx.update({ 'goal': goal, 'goal_url': goal.get_drill_down_url_for_path(tp_pootle_path), }) if can_edit: if store is None: url_kwargs = { 'language_code': language.code, 'project_code': project.code, } add_tag_action_url = reverse('pootle-xhr-tag-tp', kwargs=url_kwargs) else: add_tag_action_url = reverse('pootle-xhr-tag-store', args=[path_obj.pk]) if goal is None: edit_form = DescriptionForm(instance=translation_project) edit_form_action = reverse('pootle-tp-admin-settings', args=[language.code, project.code]) else: edit_form = GoalForm(instance=goal) edit_form_action = reverse('pootle-xhr-edit-goal', args=[goal.slug]) ctx.update({ 'form': edit_form, 'form_action': edit_form_action, 'add_tag_form': TagForm(), 'add_tag_action_url': add_tag_action_url, }) return render_to_response(template_name, ctx, context_instance=RequestContext(request))
def all_goals(self): # Putting the next import at the top of the file causes circular # import issues. from pootle_tagging.models import Goal return Goal.get_goals_for_path(self.pootle_path)
def overview(request, translation_project, dir_path, filename=None, goal=None, in_goal_overview=False): if filename: ctx = { 'store_tags': request.store.tag_like_objects, } template_name = "translation_projects/store_overview.html" else: ctx = { 'tp_tags': translation_project.tag_like_objects, } template_name = "browser/overview.html" if (check_permission('translate', request) or check_permission('suggest', request) or check_permission('overwrite', request)): ctx.update({ 'upload_form': _handle_upload_form(request, translation_project), }) can_edit = check_permission('administrate', request) project = translation_project.project language = translation_project.language resource_obj = request.store or request.directory #TODO enable again some actions when drilling down a goal. if goal is None: actions = action_groups(request, resource_obj) else: actions = [] action_output = '' running = request.GET.get(EXTDIR, '') #TODO enable the following again when drilling down a goal. if running and goal is None: if request.store: act = StoreAction else: act = TranslationProjectAction try: action = act.lookup(running) except KeyError: messages.error(request, _("Unable to find '%(action)s' in '%(extdir)s'") % {'action': act, 'extdir': running}) else: if not getattr(action, 'nosync', False): (request.store or translation_project).sync() if action.is_active(request): vcs_dir = settings.VCS_DIRECTORY po_dir = settings.PODIRECTORY tp_dir = request.directory.get_real_path() store_fn = '*' if request.store: tp_dir_slash = add_trailing_slash(tp_dir) if request.store.file.name.startswith(tp_dir_slash): # Note: store_f used below in reverse() call. store_f = request.store.file.name[len(tp_dir_slash):] store_fn = store_f.replace('/', os.sep) # Clear possibly stale output/error (even from other # resource_obj). action.set_output('') action.set_error('') try: action.run(path=resource_obj, root=po_dir, tpdir=tp_dir, project=project.code, language=language.code, store=store_fn, style=translation_project.file_style, vc_root=vcs_dir) except StandardError: err = (_("Error while running '%s' extension action") % action.title) logging.exception(err) if (action.error): messages.error(request, action.error) else: messages.error(request, err) else: if (action.error): messages.warning(request, action.error) action_output = action.output if getattr(action, 'get_download', None): export_path = action.get_download(resource_obj) if export_path: import mimetypes abs_path = absolute_real_path(export_path) filename = os.path.basename(export_path) mimetype, encoding = mimetypes.guess_type(filename) mimetype = mimetype or 'application/octet-stream' with open(abs_path, 'rb') as f: response = HttpResponse(f.read(), mimetype=mimetype) response['Content-Disposition'] = ( 'attachment; filename="%s"' % filename) return response if not action_output: if not request.store: rev_args = [language.code, project.code, ''] overview_url = reverse('pootle-tp-overview', args=rev_args) else: slash = store_f.rfind('/') store_d = '' if slash > 0: store_d = store_f[:slash] store_f = store_f[slash + 1:] elif slash == 0: store_f = store_f[1:] rev_args = [language.code, project.code, store_d, store_f] overview_url = reverse('pootle-tp-overview', args=rev_args) return HttpResponseRedirect(overview_url) if goal is None: description = translation_project.description else: description = goal.description ctx.update(get_overview_context(request)) ctx.update({ 'resource_obj': request.store or request.directory, # Dirty hack. 'translation_project': translation_project, 'description': description, 'project': project, 'language': language, 'feed_path': request.directory.pootle_path[1:], 'action_groups': actions, 'action_output': action_output, 'can_edit': can_edit, 'browser_extends': 'translation_projects/base.html', 'browser_body_id': 'tpoverview', }) tp_pootle_path = translation_project.pootle_path if request.store is None: resource_obj_goals = Goal.get_goals_for_path(resource_obj.pootle_path) resource_obj_has_goals = len(resource_obj_goals) > 0 if in_goal_overview and resource_obj_has_goals: # Then show the goals tab. table_fields = ['name', 'progress', 'priority', 'total', 'need-translation', 'suggestions'] items = [make_goal_item(resource_obj_goal, resource_obj.pootle_path) for resource_obj_goal in resource_obj_goals] ctx.update({ 'table': { 'id': 'tp-goals', 'fields': table_fields, 'headings': get_table_headings(table_fields), 'parent': get_parent(request.directory), 'items': items, }, 'resource_obj_has_goals': True, }) elif goal in resource_obj_goals: # Then show the drill down view for the specified goal. table_fields = ['name', 'progress', 'total', 'need-translation', 'suggestions', 'critical', 'activity'] ctx.update({ 'table': { 'id': 'tp-goals', 'fields': table_fields, 'headings': get_table_headings(table_fields), 'parent': get_goal_parent(request.directory, goal), 'items': get_goal_children(request.directory, goal), }, 'goal': goal, 'goal_url': goal.get_drill_down_url_for_path(tp_pootle_path), 'resource_obj_has_goals': True, }) else: # Then show the files tab. table_fields = ['name', 'progress', 'total', 'need-translation', 'suggestions', 'critical', 'activity'] ctx.update({ 'table': { 'id': 'tp-files', 'fields': table_fields, 'headings': get_table_headings(table_fields), 'parent': get_parent(request.directory), 'items': get_children(request.directory), }, 'resource_obj_has_goals': resource_obj_has_goals, }) elif goal is not None: ctx.update({ 'goal': goal, 'goal_url': goal.get_drill_down_url_for_path(tp_pootle_path), }) if can_edit: if request.store is None: url_kwargs = { 'language_code': language.code, 'project_code': project.code, } add_tag_action_url = reverse('pootle-xhr-tag-tp', kwargs=url_kwargs) else: add_tag_action_url = reverse('pootle-xhr-tag-store', args=[resource_obj.pk]) if goal is None: edit_form = DescriptionForm(instance=translation_project) edit_form_action = reverse('pootle-tp-admin-settings', args=[language.code, project.code]) else: edit_form = GoalForm(instance=goal) edit_form_action = reverse('pootle-xhr-edit-goal', args=[goal.slug]) ctx.update({ 'form': edit_form, 'form_action': edit_form_action, 'add_tag_form': TagForm(), 'add_tag_action_url': add_tag_action_url, }) return render_to_response(template_name, ctx, context_instance=RequestContext(request))
def handle(self, *args, **options): """Add project goals from file to the given project.""" project_name = options.get('project_name', None) goals_filename = options.get('goals_file', None) if project_name is None: raise CommandError("A project must be provided.") elif goals_filename is None: raise CommandError("A filename must be provided.") elif not os.path.isfile(goals_filename): raise CommandError("Filename '%s' doesn't point to an existing " "file." % goals_filename) try: project = Project.objects.get(code=project_name) except Project.DoesNotExist: raise CommandError("Project '%s' does not exist." % project_name) template_tp = project.get_template_translationproject() if not template_tp: raise CommandError("Project '%s' doesn't have a template " "translation project." % project_name) try: inputfile = open(goals_filename, "r") inputlines = inputfile.readlines() inputfile.close() except IOError as e: raise CommandError("Some error occurred while handling the file: " "%s" % e.strerror) line_number = 0 goals_dict = {} template_language = template_tp.language.code for line in inputlines: line_number += 1 line.strip() try: goal_name, filename = line.split("\t") except ValueError: raise CommandError("Wrong syntax at line %d." % line_number) # Polish the goal name and filename before working with them. filename = filename.strip().lstrip("./") filename = "/".join([project_name, template_language, filename]) goal_name = goal_name.lower() if not goal_name.startswith("goal:"): goal_name = "goal:" + goal_name try: goals_dict[goal_name].append(filename) except KeyError: goals_dict[goal_name] = [filename] logging.info("\nParsed %d lines from '%s'\n", line_number, goals_filename) # First check if any of the goals already exists and it is not a # project goal, in order to abort before creating or adding any of the # goals to the files. for goal_name in goals_dict.keys(): try: goal = Goal.objects.get(name=goal_name) if not goal.project_goal: raise CommandError("The goal '%s' already exists but it " "isn't a project goal." % goal) except Goal.DoesNotExist: pass # Criteria to get all the items in a random goal that correspond to # stores in the 'templates' translation project. # # It is used several lines below, but here is possible to calculate it # just once. stores_criteria = { 'content_type': ContentType.objects.get_for_model(Store), 'object_id__in': template_tp.stores.values_list('pk', flat=True), } applied_goals = set() # Now apply the goal to each of the stores. for goal_name in goals_dict.keys(): try: # Retrieve the goal if it already exists. goal = Goal.objects.get(name=goal_name) # Unapply the goal from all the stores in the 'templates' # translation project to which the goal is currently applied. goal.items_with_goal.filter(**stores_criteria).delete() except Goal.DoesNotExist: # If the goal doesn't exist yet then create it. criteria = { 'name': goal_name, # Note: for some unknown reason it is necessary to provide # the slug instead of letting the model create it. 'slug': slugify_tag_name(goal_name), 'project_goal': True, } try: # Get the goal priority from the end of the goal name. criteria['priority'] = int(goal_name[-1]) except ValueError: pass goal = Goal(**criteria) goal.save() for filename in goals_dict[goal_name]: try: store = template_tp.stores.get(file=filename) store.goals.add(goal) applied_goals.add(goal_name) logging.info("Goal '%s' applied to '%s'.", goal_name, filename) except ObjectDoesNotExist: logging.warning("File '%s' is not on the template " "language. Skipping it.\n", filename) logging.info("\nSucessfully added %d project goals to project '%s'.", len(applied_goals), project_name)
def get_path_summary(path_obj, path_stats, latest_action): """Returns a list of sentences to be displayed for each ``path_obj``.""" summary = [] incomplete = [] suggestions = [] if path_obj.is_dir: summary.append( ungettext("This folder has %(num)d word, %(percentage)d%% of " "which is translated.", "This folder has %(num)d words, %(percentage)d%% of " "which are translated.", path_stats['total']['words'], { 'num': path_stats['total']['words'], 'percentage': path_stats['translated']['percentage'] }) ) else: summary.append( ungettext("This file has %(num)d word, %(percentage)d%% of " "which is translated.", "This file has %(num)d words, %(percentage)d%% of " "which are translated.", path_stats['total']['words'], { 'num': path_stats['total']['words'], 'percentage': path_stats['translated']['percentage'] }) ) tp = path_obj.translation_project project = tp.project language = tp.language # Build URL for getting more summary information for the current path url_args = [language.code, project.code, path_obj.path] url_path_summary_more = reverse('tp.path_summary_more', args=url_args) summary.append(u''.join([ ' <a id="js-path-summary" data-target="js-path-summary-more" ' 'href="%s">' % url_path_summary_more, force_unicode(_(u'Expand details')), '</a>' ])) if path_stats['untranslated']['words'] > 0 or path_stats['fuzzy']['words'] > 0: num_words = path_stats['untranslated']['words'] + path_stats['fuzzy']['words'] incomplete.extend([ u'<a class="path-incomplete" href="%(url)s">' % { 'url': path_obj.get_translate_url(state='incomplete') }, ungettext(u'Continue translation (%(num)d word left)', u'Continue translation (%(num)d words left)', num_words, {'num': num_words, }), ]) if path_obj.is_dir: # Putting the next import at the top of the file causes circular # import issues. from pootle_tagging.models import Goal pootle_path = path_obj.pootle_path goal = Goal.get_most_important_incomplete_for_path(pootle_path) if goal is not None: goal_words = goal.get_incomplete_words_in_path(pootle_path) goal_url = goal.get_translate_url_for_path(pootle_path, state='incomplete') incomplete.extend([ u'<br /><a class="path-incomplete" href="%(url)s">' % { 'url': goal_url, }, ungettext(u'Next most important goal (%(num)d word left)', u'Next most important goal (%(num)d words left)', goal_words, {'num': goal_words, }), ]) else: incomplete.extend([ u'<a class="path-incomplete" href="%(url)s">' % { 'url': path_obj.get_translate_url(state='all') }, force_unicode(_('Translation is complete')), ]) incomplete.append(u'</a>') if path_stats['suggestions'] > 0: suggestions.append(u'<a class="path-incomplete" href="%(url)s">' % { 'url': path_obj.get_translate_url(state='suggestions') }) suggestions.append( ungettext(u'Review suggestion (%(num)d left)', u'Review suggestions (%(num)d left)', path_stats['suggestions'], {'num': path_stats['suggestions'], }) ) suggestions.append(u'</a>') return [u''.join(summary), latest_action, u''.join(incomplete), u''.join(suggestions)]
def overview(request, translation_project, dir_path, filename=None, goal=None, in_goal_overview=False): if filename: ctx = { 'store_tags': request.store.tag_like_objects, } template_name = "translation_projects/store_overview.html" else: ctx = { 'tp_tags': translation_project.tag_like_objects, } template_name = "browser/overview.html" if (check_permission('translate', request) or check_permission('suggest', request) or check_permission('overwrite', request)): ctx.update({ 'upload_form': _handle_upload_form(request, translation_project), }) can_edit = check_permission('administrate', request) project = translation_project.project language = translation_project.language resource_obj = request.store or request.directory #TODO enable again some actions when drilling down a goal. if goal is None: actions = action_groups(request, resource_obj) else: actions = [] action_output = '' running = request.GET.get(EXTDIR, '') #TODO enable the following again when drilling down a goal. if running and goal is None: if request.store: act = StoreAction else: act = TranslationProjectAction try: action = act.lookup(running) except KeyError: messages.error(request, _("Unable to find '%(action)s' in '%(extdir)s'") % {'action': act, 'extdir': running}) else: if not getattr(action, 'nosync', False): (request.store or translation_project).sync() if action.is_active(request): vcs_dir = settings.VCS_DIRECTORY po_dir = settings.PODIRECTORY tp_dir = request.directory.get_real_path() store_fn = '*' if request.store: tp_dir_slash = add_trailing_slash(tp_dir) if request.store.file.name.startswith(tp_dir_slash): # Note: store_f used below in reverse() call. store_f = request.store.file.name[len(tp_dir_slash):] store_fn = store_f.replace('/', os.sep) # Clear possibly stale output/error (even from other # resource_obj). action.set_output('') action.set_error('') try: action.run(path=resource_obj, root=po_dir, tpdir=tp_dir, project=project.code, language=language.code, store=store_fn, style=translation_project.file_style, vc_root=vcs_dir) except StandardError: err = (_("Error while running '%s' extension action") % action.title) logging.exception(err) if (action.error): messages.error(request, action.error) else: messages.error(request, err) else: if (action.error): messages.warning(request, action.error) action_output = action.output if getattr(action, 'get_download', None): export_path = action.get_download(resource_obj) if export_path: import mimetypes abs_path = absolute_real_path(export_path) filename = os.path.basename(export_path) mimetype, encoding = mimetypes.guess_type(filename) mimetype = mimetype or 'application/octet-stream' with open(abs_path, 'rb') as f: response = HttpResponse(f.read(), mimetype=mimetype) response['Content-Disposition'] = ( 'attachment; filename="%s"' % filename) return response if not action_output: if not request.store: rev_args = [language.code, project.code, ''] overview_url = reverse('pootle-tp-overview', args=rev_args) else: slash = store_f.rfind('/') store_d = '' if slash > 0: store_d = store_f[:slash] store_f = store_f[slash + 1:] elif slash == 0: store_f = store_f[1:] rev_args = [language.code, project.code, store_d, store_f] overview_url = reverse('pootle-tp-overview', args=rev_args) return HttpResponseRedirect(overview_url) if goal is None: description = translation_project.description else: description = goal.description # TODO: cleanup and refactor, retrieve from cache try: ann_virtual_path = 'announcements/' + project.code announcement = StaticPage.objects.live(request.user).get( virtual_path=ann_virtual_path, ) except StaticPage.DoesNotExist: announcement = None display_announcement = True stored_mtime = None new_mtime = None cookie_data = {} if ANN_COOKIE_NAME in request.COOKIES: json_str = unquote(request.COOKIES[ANN_COOKIE_NAME]) cookie_data = simplejson.loads(json_str) if 'isOpen' in cookie_data: display_announcement = cookie_data['isOpen'] if project.code in cookie_data: stored_mtime = cookie_data[project.code] if announcement is not None: ann_mtime = dateformat.format(announcement.modified_on, 'U') if ann_mtime != stored_mtime: display_announcement = True new_mtime = ann_mtime ctx.update(get_overview_context(request)) ctx.update({ 'resource_obj': request.store or request.directory, # Dirty hack. 'translation_project': translation_project, 'description': description, 'project': project, 'language': language, 'feed_path': request.directory.pootle_path[1:], 'action_groups': actions, 'action_output': action_output, 'can_edit': can_edit, 'browser_extends': 'translation_projects/base.html', 'browser_body_id': 'tpoverview', 'announcement': announcement, 'announcement_displayed': display_announcement, }) tp_pootle_path = translation_project.pootle_path if request.store is None: resource_obj_goals = Goal.get_goals_for_path(resource_obj.pootle_path) resource_obj_has_goals = len(resource_obj_goals) > 0 if in_goal_overview and resource_obj_has_goals: # Then show the goals tab. table_fields = ['name', 'progress', 'priority', 'total', 'need-translation', 'suggestions'] items = [make_goal_item(resource_obj_goal, resource_obj.pootle_path) for resource_obj_goal in resource_obj_goals] ctx.update({ 'table': { 'id': 'tp-goals', 'fields': table_fields, 'headings': get_table_headings(table_fields), 'parent': get_parent(request.directory), 'items': items, }, 'resource_obj_has_goals': True, }) elif goal in resource_obj_goals: # Then show the drill down view for the specified goal. table_fields = ['name', 'progress', 'total', 'need-translation', 'suggestions', 'critical', 'last-updated', 'activity'] ctx.update({ 'table': { 'id': 'tp-goals', 'fields': table_fields, 'headings': get_table_headings(table_fields), 'parent': get_goal_parent(request.directory, goal), 'items': get_goal_children(request.directory, goal), }, 'goal': goal, 'goal_url': goal.get_drill_down_url_for_path(tp_pootle_path), 'resource_obj_has_goals': True, }) else: # Then show the files tab. table_fields = ['name', 'progress', 'total', 'need-translation', 'suggestions', 'critical', 'last-updated', 'activity'] ctx.update({ 'table': { 'id': 'tp-files', 'fields': table_fields, 'headings': get_table_headings(table_fields), 'parent': get_parent(request.directory), 'items': get_children(request.directory), }, 'resource_obj_has_goals': resource_obj_has_goals, }) elif goal is not None: ctx.update({ 'goal': goal, 'goal_url': goal.get_drill_down_url_for_path(tp_pootle_path), }) if can_edit: if request.store is None: url_kwargs = { 'language_code': language.code, 'project_code': project.code, } add_tag_action_url = reverse('pootle-xhr-tag-tp', kwargs=url_kwargs) else: add_tag_action_url = reverse('pootle-xhr-tag-store', args=[resource_obj.pk]) if goal is None: edit_form = DescriptionForm(instance=translation_project) edit_form_action = reverse('pootle-tp-admin-settings', args=[language.code, project.code]) else: edit_form = GoalForm(instance=goal) edit_form_action = reverse('pootle-xhr-edit-goal', args=[goal.slug]) ctx.update({ 'form': edit_form, 'form_action': edit_form_action, 'add_tag_form': TagForm(), 'add_tag_action_url': add_tag_action_url, }) response = render_to_response(template_name, ctx, context_instance=RequestContext(request)) if new_mtime is not None: cookie_data[project.code] = new_mtime cookie_data = quote(simplejson.dumps(cookie_data)) response.set_cookie(ANN_COOKIE_NAME, cookie_data) return response
def overview(request, translation_project, dir_path, filename=None, goal=None, in_goal_overview=False): if filename: ctx = {"store_tags": request.store.tag_like_objects} template_name = "translation_projects/store_overview.html" else: ctx = {"tp_tags": translation_project.tag_like_objects} template_name = "browser/overview.html" if ( check_permission("translate", request) or check_permission("suggest", request) or check_permission("overwrite", request) ): ctx.update({"upload_form": _handle_upload_form(request, translation_project)}) can_edit = check_permission("administrate", request) project = translation_project.project language = translation_project.language resource_obj = request.store or request.directory # TODO enable again some actions when drilling down a goal. if goal is None: actions = action_groups(request, resource_obj) else: actions = [] action_output = "" running = request.GET.get(EXTDIR, "") # TODO enable the following again when drilling down a goal. if running and goal is None: if request.store: act = StoreAction else: act = TranslationProjectAction try: action = act.lookup(running) except KeyError: messages.error( request, _("Unable to find '%(action)s' in '%(extdir)s'") % {"action": act, "extdir": running} ) else: if not getattr(action, "nosync", False): (request.store or translation_project).sync() if action.is_active(request): vcs_dir = settings.VCS_DIRECTORY po_dir = settings.PODIRECTORY tp_dir = request.directory.get_real_path() store_fn = "*" if request.store: tp_dir_slash = add_trailing_slash(tp_dir) if request.store.file.name.startswith(tp_dir_slash): # Note: store_f used below in reverse() call. store_f = request.store.file.name[len(tp_dir_slash) :] store_fn = store_f.replace("/", os.sep) # Clear possibly stale output/error (even from other # resource_obj). action.set_output("") action.set_error("") try: action.run( path=resource_obj, root=po_dir, tpdir=tp_dir, project=project.code, language=language.code, store=store_fn, style=translation_project.file_style, vc_root=vcs_dir, ) except StandardError: err = _("Error while running '%s' extension action") % action.title logging.exception(err) if action.error: messages.error(request, action.error) else: messages.error(request, err) else: if action.error: messages.warning(request, action.error) action_output = action.output if getattr(action, "get_download", None): export_path = action.get_download(resource_obj) if export_path: import mimetypes abs_path = absolute_real_path(export_path) filename = os.path.basename(export_path) mimetype, encoding = mimetypes.guess_type(filename) mimetype = mimetype or "application/octet-stream" with open(abs_path, "rb") as f: response = HttpResponse(f.read(), mimetype=mimetype) response["Content-Disposition"] = 'attachment; filename="%s"' % filename return response if not action_output: if not request.store: rev_args = [language.code, project.code, ""] overview_url = reverse("pootle-tp-overview", args=rev_args) else: slash = store_f.rfind("/") store_d = "" if slash > 0: store_d = store_f[:slash] store_f = store_f[slash + 1 :] elif slash == 0: store_f = store_f[1:] rev_args = [language.code, project.code, store_d, store_f] overview_url = reverse("pootle-tp-overview", args=rev_args) return HttpResponseRedirect(overview_url) if goal is None: description = translation_project.description else: description = goal.description ctx.update(get_overview_context(request)) ctx.update( { "resource_obj": request.store or request.directory, # Dirty hack. "translation_project": translation_project, "description": description, "project": project, "language": language, "feed_path": request.directory.pootle_path[1:], "action_groups": actions, "action_output": action_output, "can_edit": can_edit, "browser_extends": "translation_projects/base.html", "browser_body_id": "tpoverview", } ) tp_pootle_path = translation_project.pootle_path if request.store is None: resource_obj_goals = Goal.get_goals_for_path(resource_obj.pootle_path) resource_obj_has_goals = len(resource_obj_goals) > 0 if in_goal_overview and resource_obj_has_goals: # Then show the goals tab. table_fields = ["name", "progress", "priority", "total", "need-translation", "suggestions"] items = [ make_goal_item(resource_obj_goal, resource_obj.pootle_path) for resource_obj_goal in resource_obj_goals ] ctx.update( { "table": { "id": "tp-goals", "fields": table_fields, "headings": get_table_headings(table_fields), "parent": get_parent(request.directory), "items": items, }, "resource_obj_has_goals": True, } ) elif goal in resource_obj_goals: # Then show the drill down view for the specified goal. table_fields = ["name", "progress", "total", "need-translation", "suggestions", "critical", "activity"] ctx.update( { "table": { "id": "tp-goals", "fields": table_fields, "headings": get_table_headings(table_fields), "parent": get_goal_parent(request.directory, goal), "items": get_goal_children(request.directory, goal), }, "goal": goal, "goal_url": goal.get_drill_down_url_for_path(tp_pootle_path), "resource_obj_has_goals": True, } ) else: # Then show the files tab. table_fields = ["name", "progress", "total", "need-translation", "suggestions", "critical", "activity"] ctx.update( { "table": { "id": "tp-files", "fields": table_fields, "headings": get_table_headings(table_fields), "parent": get_parent(request.directory), "items": get_children(request.directory), }, "resource_obj_has_goals": resource_obj_has_goals, } ) elif goal is not None: ctx.update({"goal": goal, "goal_url": goal.get_drill_down_url_for_path(tp_pootle_path)}) if can_edit: if request.store is None: url_kwargs = {"language_code": language.code, "project_code": project.code} add_tag_action_url = reverse("pootle-xhr-tag-tp", kwargs=url_kwargs) else: add_tag_action_url = reverse("pootle-xhr-tag-store", args=[resource_obj.pk]) if goal is None: edit_form = DescriptionForm(instance=translation_project) edit_form_action = reverse("pootle-tp-admin-settings", args=[language.code, project.code]) else: edit_form = GoalForm(instance=goal) edit_form_action = reverse("pootle-xhr-edit-goal", args=[goal.slug]) ctx.update( { "form": edit_form, "form_action": edit_form_action, "add_tag_form": TagForm(), "add_tag_action_url": add_tag_action_url, } ) return render_to_response(template_name, ctx, context_instance=RequestContext(request))