Example #1
0
def test_project_add_locale(client_superuser):
    locale_kl = LocaleFactory.create(code="kl", name="Klingon")
    locale_gs = LocaleFactory.create(code="gs", name="Geonosian")
    project = ProjectFactory.create(
        data_source=Project.DataSource.DATABASE,
        locales=[locale_kl],
        repositories=[],
    )
    _create_or_update_translated_resources(project, [locale_kl])

    url = reverse("pontoon.admin.project", args=(project.slug,))

    # Boring data creation for FormSets. Django is painful with that,
    # or I don't know how to handle that more gracefully.
    form = ProjectForm(instance=project)
    form_data = dict(form.initial)
    del form_data["width"]
    del form_data["deadline"]
    del form_data["contact"]
    form_data.update(
        {
            "subpage_set-INITIAL_FORMS": "0",
            "subpage_set-TOTAL_FORMS": "1",
            "subpage_set-MIN_NUM_FORMS": "0",
            "subpage_set-MAX_NUM_FORMS": "1000",
            "externalresource_set-TOTAL_FORMS": "1",
            "externalresource_set-MAX_NUM_FORMS": "1000",
            "externalresource_set-MIN_NUM_FORMS": "0",
            "externalresource_set-INITIAL_FORMS": "0",
            "tag_set-TOTAL_FORMS": "1",
            "tag_set-INITIAL_FORMS": "0",
            "tag_set-MAX_NUM_FORMS": "1000",
            "tag_set-MIN_NUM_FORMS": "0",
            "repositories-INITIAL_FORMS": "0",
            "repositories-MIN_NUM_FORMS": "0",
            "repositories-MAX_NUM_FORMS": "1000",
            "repositories-TOTAL_FORMS": "0",
            # These are the values that actually matter.
            "pk": project.pk,
            "locales": [locale_kl.id, locale_gs.id],
            "configuration_file": "",
        }
    )

    response = client_superuser.post(url, form_data)
    assert response.status_code == 200
    assert b". Error." not in response.content

    # Verify we have the right ProjectLocale objects.
    pl = ProjectLocale.objects.filter(project=project)
    assert len(pl) == 2

    # Verify that TranslatedResource objects have been created.
    resource = Resource.objects.get(project=project, path="database")
    tr = TranslatedResource.objects.filter(resource=resource)
    assert len(tr) == 2
Example #2
0
def test_project_add_locale(client_superuser):
    locale_kl = LocaleFactory.create(code='kl', name='Klingon')
    locale_gs = LocaleFactory.create(code='gs', name='Geonosian')
    project = ProjectFactory.create(
        data_source='database',
        locales=[locale_kl],
        repositories=[],
    )
    _create_or_update_translated_resources(project, [locale_kl])

    url = reverse('pontoon.admin.project', args=(project.slug, ))

    # Boring data creation for FormSets. Django is painful with that,
    # or I don't know how to handle that more gracefully.
    form = ProjectForm(instance=project)
    form_data = dict(form.initial)
    del form_data['width']
    del form_data['deadline']
    del form_data['contact']
    form_data.update({
        'subpage_set-INITIAL_FORMS': '0',
        'subpage_set-TOTAL_FORMS': '1',
        'subpage_set-MIN_NUM_FORMS': '0',
        'subpage_set-MAX_NUM_FORMS': '1000',
        'externalresource_set-TOTAL_FORMS': '1',
        'externalresource_set-MAX_NUM_FORMS': '1000',
        'externalresource_set-MIN_NUM_FORMS': '0',
        'externalresource_set-INITIAL_FORMS': '0',
        'tag_set-TOTAL_FORMS': '1',
        'tag_set-INITIAL_FORMS': '0',
        'tag_set-MAX_NUM_FORMS': '1000',
        'tag_set-MIN_NUM_FORMS': '0',
        'repositories-INITIAL_FORMS': '0',
        'repositories-MIN_NUM_FORMS': '0',
        'repositories-MAX_NUM_FORMS': '1000',
        'repositories-TOTAL_FORMS': '0',
        # These are the values that actually matter.
        'pk': project.pk,
        'locales': [locale_kl.id, locale_gs.id],
    })

    response = client_superuser.post(url, form_data)
    assert response.status_code == 200
    assert b'. Error.' not in response.content

    # Verify we have the right ProjectLocale objects.
    pl = ProjectLocale.objects.filter(project=project)
    assert len(pl) == 2

    # Verify that TranslatedResource objects have been created.
    resource = Resource.objects.get(project=project, path='database')
    tr = TranslatedResource.objects.filter(resource=resource)
    assert len(tr) == 2
Example #3
0
def manage_project(request, slug=None, template='admin_project.html'):
    """Admin project."""
    log.debug("Admin project.")

    if not request.user.has_perm('base.can_manage'):
        return render(request, '403.html', status=403)

    form = ProjectForm()
    subpage_formset = SubpageInlineFormSet()
    repo_formset = RepositoryInlineFormSet()
    locales_selected = []
    subtitle = 'Add project'
    pk = None
    project = None

    # Save project
    if request.method == 'POST':
        locales_selected = Locale.objects.filter(
            pk__in=request.POST.getlist('locales'))

        # Update existing project
        try:
            pk = request.POST['pk']
            project = Project.objects.get(pk=pk)
            form = ProjectForm(request.POST, instance=project)
            # Needed if form invalid
            subpage_formset = SubpageInlineFormSet(request.POST, instance=project)
            repo_formset = RepositoryInlineFormSet(request.POST, instance=project)
            subtitle = 'Edit project'

        # Add a new project
        except MultiValueDictKeyError:
            form = ProjectForm(request.POST)
            # Needed if form invalid
            subpage_formset = SubpageInlineFormSet(request.POST)
            repo_formset = RepositoryInlineFormSet(request.POST)

        if form.is_valid():
            project = form.save(commit=False)
            subpage_formset = SubpageInlineFormSet(request.POST, instance=project)
            repo_formset = RepositoryInlineFormSet(request.POST, instance=project)

            if subpage_formset.is_valid() and repo_formset.is_valid():
                project.save()

                # Manually save ProjectLocales due to intermediary
                # model.
                locales = form.cleaned_data.get('locales', [])
                (ProjectLocale.objects
                    .filter(project=project)
                    .exclude(locale__pk__in=[l.pk for l in locales])
                    .delete())
                for locale in locales:
                    ProjectLocale.objects.get_or_create(project=project, locale=locale)

                subpage_formset.save()
                repo_formset.save()
                # Properly displays formsets, but removes errors (if valid only)
                subpage_formset = SubpageInlineFormSet(instance=project)
                repo_formset = RepositoryInlineFormSet(instance=project)
                subtitle += '. Saved.'
                pk = project.pk
            else:
                subtitle += '. Error.'
        else:
            subtitle += '. Error.'

    # If URL specified and found, show edit, otherwise show add form
    elif slug is not None:
        try:
            project = Project.objects.get(slug=slug)
            pk = project.pk
            form = ProjectForm(instance=project)
            subpage_formset = SubpageInlineFormSet(instance=project)
            repo_formset = RepositoryInlineFormSet(instance=project)
            locales_selected = project.locales.all()
            subtitle = 'Edit project'
        except Project.DoesNotExist:
            form = ProjectForm(initial={'slug': slug})

    # Override default label suffix
    form.label_suffix = ''

    data = {
        'form': form,
        'subpage_formset': subpage_formset,
        'repo_formset': repo_formset,
        'locales_selected': locales_selected,
        'locales_available': Locale.objects.exclude(pk__in=locales_selected),
        'subtitle': subtitle,
        'pk': pk,
    }

    # Set locale in Translate link
    if hasattr(project, 'locales') and locales_selected:
        locale = utils.get_project_locale_from_request(
            request, project.locales) or locales_selected[0].code
        if locale:
            data['translate_locale'] = locale

    if Resource.objects.filter(project=project).exists():
        data['ready'] = True

    return render(request, template, data)
Example #4
0
def manage_project(request, slug=None, template='admin_project.html'):
    """Admin project."""
    log.debug("Admin project.")

    if not request.user.has_perm('base.can_manage_project'):
        raise PermissionDenied

    form = ProjectForm()
    subpage_formset = SubpageInlineFormSet()
    repo_formset = RepositoryInlineFormSet()
    external_resource_formset = ExternalResourceInlineFormSet()
    tag_formset = TagInlineFormSet()
    locales_readonly = []
    locales_selected = []
    subtitle = 'Add project'
    pk = None
    project = None

    # Save project
    if request.method == 'POST':
        locales_readonly = Locale.objects.filter(
            pk__in=request.POST.getlist('locales_readonly'))
        locales_selected = Locale.objects.filter(
            pk__in=request.POST.getlist('locales')).exclude(
                pk__in=locales_readonly)

        # Update existing project
        try:
            pk = request.POST['pk']
            project = Project.objects.get(pk=pk)
            form = ProjectForm(request.POST, instance=project)
            # Needed if form invalid
            subpage_formset = SubpageInlineFormSet(request.POST,
                                                   instance=project)
            repo_formset = RepositoryInlineFormSet(request.POST,
                                                   instance=project)
            tag_formset = (TagInlineFormSet(request.POST, instance=project)
                           if project.tags_enabled else None)
            external_resource_formset = ExternalResourceInlineFormSet(
                request.POST, instance=project)
            subtitle = 'Edit project'

        # Add a new project
        except MultiValueDictKeyError:
            form = ProjectForm(request.POST)
            # Needed if form invalid
            subpage_formset = SubpageInlineFormSet(request.POST)
            repo_formset = RepositoryInlineFormSet(request.POST)
            external_resource_formset = ExternalResourceInlineFormSet(
                request.POST)
            tag_formset = None

        if form.is_valid():
            project = form.save(commit=False)
            subpage_formset = SubpageInlineFormSet(request.POST,
                                                   instance=project)
            repo_formset = RepositoryInlineFormSet(request.POST,
                                                   instance=project)
            external_resource_formset = ExternalResourceInlineFormSet(
                request.POST, instance=project)
            if tag_formset:
                tag_formset = TagInlineFormSet(request.POST, instance=project)
            formsets_valid = (
                subpage_formset.is_valid() and repo_formset.is_valid()
                and external_resource_formset.is_valid()
                and (tag_formset.is_valid() if tag_formset else True))
            if formsets_valid:
                project.save()

                # Manually save ProjectLocales due to intermediary model
                locales_form = form.cleaned_data.get('locales', [])
                locales_readonly_form = form.cleaned_data.get(
                    'locales_readonly', [])
                locales = locales_form | locales_readonly_form

                (ProjectLocale.objects.filter(project=project).exclude(
                    locale__pk__in=[l.pk for l in locales]).delete())
                for locale in locales:
                    ProjectLocale.objects.get_or_create(project=project,
                                                        locale=locale)

                # Update readonly flags
                locales_readonly_pks = [l.pk for l in locales_readonly_form]
                project_locales = ProjectLocale.objects.filter(project=project)
                project_locales.exclude(
                    locale__pk__in=locales_readonly_pks).update(readonly=False)
                project_locales.filter(
                    locale__pk__in=locales_readonly_pks, ).update(
                        readonly=True)

                subpage_formset.save()
                repo_formset.save()
                external_resource_formset.save()
                if tag_formset:
                    tag_formset.save()

                # If the data source is database and there are new strings, save them.
                if project.data_source == 'database':
                    _save_new_strings(project,
                                      request.POST.get('new_strings', ''))
                    _create_or_update_translated_resources(project, locales)

                # Properly displays formsets, but removes errors (if valid only)
                subpage_formset = SubpageInlineFormSet(instance=project)
                repo_formset = RepositoryInlineFormSet(instance=project)
                external_resource_formset = ExternalResourceInlineFormSet(
                    instance=project)
                if project.tags_enabled:
                    tag_formset = TagInlineFormSet(instance=project)
                subtitle += '. Saved.'
                pk = project.pk
            else:
                subtitle += '. Error.'
        else:
            subtitle += '. Error.'

    # If URL specified and found, show edit, otherwise show add form
    elif slug is not None:
        try:
            project = Project.objects.get(slug=slug)
            pk = project.pk
            form = ProjectForm(instance=project)
            subpage_formset = SubpageInlineFormSet(instance=project)
            repo_formset = RepositoryInlineFormSet(instance=project)
            tag_formset = (TagInlineFormSet(
                instance=project) if project.tags_enabled else None)
            external_resource_formset = ExternalResourceInlineFormSet(
                instance=project)
            locales_readonly = Locale.objects.filter(
                project_locale__readonly=True,
                project_locale__project=project,
            )
            locales_selected = project.locales.exclude(pk__in=locales_readonly)
            subtitle = 'Edit project'
        except Project.DoesNotExist:
            form = ProjectForm(initial={'slug': slug})

    # Override default label suffix
    form.label_suffix = ''

    projects = []
    for p in Project.objects.prefetch_related('locales').order_by('name'):
        projects.append({
            'name': p.name,
            # Cannot use values_list() here, because it hits the DB again
            'locales': [l.pk for l in p.locales.all()],
        })

    data = {
        'slug': slug,
        'form': form,
        'subpage_formset': subpage_formset,
        'repo_formset': repo_formset,
        'tag_formset': tag_formset,
        'external_resource_formset': external_resource_formset,
        'locales_readonly': locales_readonly,
        'locales_selected': locales_selected,
        'locales_available': Locale.objects.exclude(pk__in=locales_selected),
        'subtitle': subtitle,
        'pk': pk,
        'project': project,
        'projects': projects,
    }

    # Set locale in Translate link
    if hasattr(project, 'locales') and locales_selected:
        locale = utils.get_project_locale_from_request(
            request, project.locales) or locales_selected[0].code
        if locale:
            data['translate_locale'] = locale

    if Resource.objects.filter(project=project).exists():
        data['ready'] = True

    return render(request, template, data)
Example #5
0
def manage_project(request, slug=None, template='admin_project.html'):
    """Admin project."""
    log.debug("Admin project.")

    if not request.user.has_perm('base.can_manage_project'):
        raise PermissionDenied

    form = ProjectForm()
    subpage_formset = SubpageInlineFormSet()
    repo_formset = RepositoryInlineFormSet()
    external_resource_formset = ExternalResourceInlineFormSet()
    tag_formset = TagInlineFormSet()
    locales_readonly = Locale.objects.none()
    locales_selected = Locale.objects.none()
    subtitle = 'Add project'
    pk = None
    project = None

    # Save project
    if request.method == 'POST':
        locales_readonly = Locale.objects.filter(
            pk__in=request.POST.getlist('locales_readonly')
        )
        locales_selected = Locale.objects.filter(
            pk__in=request.POST.getlist('locales')
        ).exclude(
            pk__in=locales_readonly
        )

        # Update existing project
        try:
            pk = request.POST['pk']
            project = Project.objects.get(pk=pk)
            form = ProjectForm(request.POST, instance=project)
            # Needed if form invalid
            subpage_formset = SubpageInlineFormSet(request.POST, instance=project)
            repo_formset = RepositoryInlineFormSet(request.POST, instance=project)
            tag_formset = (
                TagInlineFormSet(request.POST, instance=project)
                if project.tags_enabled
                else None
            )
            external_resource_formset = ExternalResourceInlineFormSet(
                request.POST, instance=project
            )
            subtitle = 'Edit project'

        # Add a new project
        except MultiValueDictKeyError:
            form = ProjectForm(request.POST)
            # Needed if form invalid
            subpage_formset = SubpageInlineFormSet(request.POST)
            repo_formset = RepositoryInlineFormSet(request.POST)
            external_resource_formset = ExternalResourceInlineFormSet(request.POST)
            tag_formset = None

        if form.is_valid():
            project = form.save(commit=False)
            subpage_formset = SubpageInlineFormSet(request.POST, instance=project)
            repo_formset = RepositoryInlineFormSet(request.POST, instance=project)
            external_resource_formset = ExternalResourceInlineFormSet(
                request.POST, instance=project
            )
            if tag_formset:
                tag_formset = TagInlineFormSet(request.POST, instance=project)
            formsets_valid = (
                subpage_formset.is_valid()
                and repo_formset.is_valid()
                and external_resource_formset.is_valid()
                and (tag_formset.is_valid() if tag_formset else True)
            )
            if formsets_valid:
                project.save()

                # Manually save ProjectLocales due to intermediary model
                locales_form = form.cleaned_data.get('locales', [])
                locales_readonly_form = form.cleaned_data.get('locales_readonly', [])
                locales = locales_form | locales_readonly_form

                (
                    ProjectLocale.objects
                    .filter(project=project)
                    .exclude(locale__pk__in=[l.pk for l in locales])
                    .delete()
                )
                for locale in locales:
                    ProjectLocale.objects.get_or_create(project=project, locale=locale)

                # Update readonly flags
                locales_readonly_pks = [l.pk for l in locales_readonly_form]
                project_locales = ProjectLocale.objects.filter(project=project)
                project_locales.exclude(
                    locale__pk__in=locales_readonly_pks
                ).update(readonly=False)
                project_locales.filter(
                    locale__pk__in=locales_readonly_pks,
                ).update(readonly=True)

                subpage_formset.save()
                repo_formset.save()
                external_resource_formset.save()
                if tag_formset:
                    tag_formset.save()

                # If the data source is database and there are new strings, save them.
                if project.data_source == 'database':
                    _save_new_strings(project, request.POST.get('new_strings', ''))
                    _create_or_update_translated_resources(project, locales)

                # Properly displays formsets, but removes errors (if valid only)
                subpage_formset = SubpageInlineFormSet(instance=project)
                repo_formset = RepositoryInlineFormSet(instance=project)
                external_resource_formset = ExternalResourceInlineFormSet(instance=project)
                if project.tags_enabled:
                    tag_formset = TagInlineFormSet(instance=project)
                subtitle += '. Saved.'
                pk = project.pk
            else:
                subtitle += '. Error.'
        else:
            subtitle += '. Error.'

    # If URL specified and found, show edit, otherwise show add form
    elif slug is not None:
        try:
            project = Project.objects.get(slug=slug)
            pk = project.pk
            form = ProjectForm(instance=project)
            subpage_formset = SubpageInlineFormSet(instance=project)
            repo_formset = RepositoryInlineFormSet(instance=project)
            tag_formset = (
                TagInlineFormSet(instance=project)
                if project.tags_enabled
                else None
            )
            external_resource_formset = ExternalResourceInlineFormSet(instance=project)
            locales_readonly = Locale.objects.filter(
                project_locale__readonly=True,
                project_locale__project=project,
            )
            locales_selected = project.locales.exclude(pk__in=locales_readonly)
            subtitle = 'Edit project'
        except Project.DoesNotExist:
            form = ProjectForm(initial={'slug': slug})

    # Override default label suffix
    form.label_suffix = ''

    projects = []
    for p in Project.objects.prefetch_related('locales').order_by('name'):
        projects.append({
            'name': p.name,
            # Cannot use values_list() here, because it hits the DB again
            'locales': [l.pk for l in p.locales.all()],
        })
        
    locales_available = Locale.objects.exclude(pk__in=locales_selected)
    
    # Admins reason in terms of locale codes (see bug 1394194)
    locales_readonly = locales_readonly.order_by('code')
    locales_selected = locales_selected.order_by('code')
    locales_available = locales_available.order_by('code')

    data = {
        'slug': slug,
        'form': form,
        'subpage_formset': subpage_formset,
        'repo_formset': repo_formset,
        'tag_formset': tag_formset,
        'external_resource_formset': external_resource_formset,
        'locales_readonly': locales_readonly,
        'locales_selected': locales_selected,
        'locales_available': locales_available,
        'subtitle': subtitle,
        'pk': pk,
        'project': project,
        'projects': projects,
    }

    # Set locale in Translate link
    if hasattr(project, 'locales') and locales_selected:
        locale = utils.get_project_locale_from_request(
            request, project.locales) or locales_selected[0].code
        if locale:
            data['translate_locale'] = locale

    if Resource.objects.filter(project=project).exists():
        data['ready'] = True

    return render(request, template, data)
Example #6
0
def manage_project(request, slug=None, template="admin_project.html"):
    """Admin project."""
    log.debug("Admin project.")

    if not request.user.has_perm("base.can_manage_project"):
        raise PermissionDenied

    form = ProjectForm()
    subpage_formset = SubpageInlineFormSet()
    repo_formset = RepositoryInlineFormSet()
    external_resource_formset = ExternalResourceInlineFormSet()
    tag_formset = TagInlineFormSet()
    locales_readonly = Locale.objects.none()
    locales_selected = Locale.objects.none()
    subtitle = "Add project"
    pk = None
    project = None

    # Save project
    if request.method == "POST":
        locales_readonly = Locale.objects.filter(
            pk__in=request.POST.getlist("locales_readonly"))
        locales_selected = Locale.objects.filter(
            pk__in=request.POST.getlist("locales")).exclude(
                pk__in=locales_readonly)

        # Update existing project
        try:
            pk = request.POST["pk"]
            project = Project.objects.visible_for(request.user).get(pk=pk)
            form = ProjectForm(request.POST, instance=project)
            # Needed if form invalid
            subpage_formset = SubpageInlineFormSet(request.POST,
                                                   instance=project)
            repo_formset = RepositoryInlineFormSet(request.POST,
                                                   instance=project)
            tag_formset = (TagInlineFormSet(request.POST, instance=project)
                           if project.tags_enabled else None)
            external_resource_formset = ExternalResourceInlineFormSet(
                request.POST, instance=project)
            subtitle = "Edit project"

        # Add a new project
        except MultiValueDictKeyError:
            form = ProjectForm(request.POST)
            # Needed if form invalid
            subpage_formset = SubpageInlineFormSet(request.POST)
            repo_formset = RepositoryInlineFormSet(request.POST)
            external_resource_formset = ExternalResourceInlineFormSet(
                request.POST)
            tag_formset = None

        if form.is_valid():
            project = form.save(commit=False)
            subpage_formset = SubpageInlineFormSet(request.POST,
                                                   instance=project)
            repo_formset = RepositoryInlineFormSet(request.POST,
                                                   instance=project)
            external_resource_formset = ExternalResourceInlineFormSet(
                request.POST, instance=project)
            if tag_formset:
                tag_formset = TagInlineFormSet(request.POST, instance=project)
            formsets_valid = (
                subpage_formset.is_valid() and repo_formset.is_valid()
                and external_resource_formset.is_valid()
                and (tag_formset.is_valid() if tag_formset else True))
            if formsets_valid:
                project.save()

                # Manually save ProjectLocales due to intermediary model
                locales_form = form.cleaned_data.get("locales", [])
                locales_readonly_form = form.cleaned_data.get(
                    "locales_readonly", [])
                locales = locales_form | locales_readonly_form

                (ProjectLocale.objects.filter(project=project).exclude(
                    locale__pk__in=[l.pk for l in locales]).delete())
                for locale in locales:
                    ProjectLocale.objects.get_or_create(project=project,
                                                        locale=locale)

                # Update readonly flags
                locales_readonly_pks = [l.pk for l in locales_readonly_form]
                project_locales = ProjectLocale.objects.filter(project=project)
                project_locales.exclude(
                    locale__pk__in=locales_readonly_pks).update(readonly=False)
                project_locales.filter(
                    locale__pk__in=locales_readonly_pks, ).update(
                        readonly=True)

                subpage_formset.save()
                repo_formset.save()
                external_resource_formset.save()
                if tag_formset:
                    tag_formset.save()

                # If the data source is database and there are new strings, save them.
                if project.data_source == Project.DataSource.DATABASE:
                    _save_new_strings(project,
                                      request.POST.get("new_strings", ""))
                    _create_or_update_translated_resources(project, locales)

                # Properly displays formsets, but removes errors (if valid only)
                subpage_formset = SubpageInlineFormSet(instance=project)
                repo_formset = RepositoryInlineFormSet(instance=project)
                external_resource_formset = ExternalResourceInlineFormSet(
                    instance=project)
                if project.tags_enabled:
                    tag_formset = TagInlineFormSet(instance=project)
                subtitle += ". Saved."
                pk = project.pk
            else:
                subtitle += ". Error."
        else:
            subtitle += ". Error."

    # If URL specified and found, show edit, otherwise show add form
    elif slug is not None:
        try:
            project = Project.objects.get(slug=slug)
            pk = project.pk
            form = ProjectForm(instance=project)
            subpage_formset = SubpageInlineFormSet(instance=project)
            repo_formset = RepositoryInlineFormSet(instance=project)
            tag_formset = (TagInlineFormSet(
                instance=project) if project.tags_enabled else None)
            external_resource_formset = ExternalResourceInlineFormSet(
                instance=project)
            locales_readonly = Locale.objects.filter(
                project_locale__readonly=True,
                project_locale__project=project,
            )
            locales_selected = project.locales.exclude(pk__in=locales_readonly)
            subtitle = "Edit project"
        except Project.DoesNotExist:
            form = ProjectForm(initial={"slug": slug})

    # Override default label suffix
    form.label_suffix = ""

    projects = []
    for p in Project.objects.prefetch_related("locales").order_by("name"):
        projects.append({
            "name": p.name,
            # Cannot use values_list() here, because it hits the DB again
            "locales": [l.pk for l in p.locales.all()],
        })

    locales_available = Locale.objects.exclude(
        pk__in=locales_readonly).exclude(pk__in=locales_selected)

    # Admins reason in terms of locale codes (see bug 1394194)
    locales_readonly = locales_readonly.order_by("code")
    locales_selected = locales_selected.order_by("code")
    locales_available = locales_available.order_by("code")

    data = {
        "slug": slug,
        "form": form,
        "subpage_formset": subpage_formset,
        "repo_formset": repo_formset,
        "tag_formset": tag_formset,
        "external_resource_formset": external_resource_formset,
        "locales_readonly": locales_readonly,
        "locales_selected": locales_selected,
        "locales_available": locales_available,
        "subtitle": subtitle,
        "pk": pk,
        "project": project,
        "projects": projects,
    }

    # Set locale in Translate link
    if Resource.objects.filter(project=project).exists() and locales_selected:
        locale = (utils.get_project_locale_from_request(
            request, project.locales) or locales_selected[0].code)
        if locale:
            data["translate_locale"] = locale

    return render(request, template, data)