-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
fix: add intermediate page for project-language upload #17534
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
21955e3
9ac9af5
9f4e192
d1a1732
05e9260
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -312,7 +312,9 @@ def check_unit_review( | |
|
|
||
| @register_perm("unit.edit", "suggestion.accept") | ||
| def check_edit_approved( | ||
| user: User, permission: str, obj: Unit | Translation | Component | Project | ||
| user: User, | ||
| permission: str, | ||
| obj: Unit | Translation | Component | Project | ProjectLanguage, | ||
| ) -> bool | PermissionResult: | ||
| component = None | ||
| if isinstance(obj, Unit): | ||
|
|
@@ -460,7 +462,7 @@ def check_suggestion_vote( | |
|
|
||
| @register_perm("suggestion.add") | ||
| def check_suggestion_add( | ||
| user: User, permission: str, obj: Unit | Translation | ||
| user: User, permission: str, obj: Unit | Translation | ProjectLanguage | ||
| ) -> bool | PermissionResult: | ||
| if isinstance(obj, Unit): | ||
| obj = obj.translation | ||
|
|
@@ -469,6 +471,7 @@ def check_suggestion_add( | |
| # Check contributor license agreement | ||
| if ( | ||
| not user.is_bot | ||
| and isinstance(obj, Translation) | ||
| and obj.component.agreement | ||
| and not ContributorAgreement.objects.has_agreed(user, obj.component) | ||
| ): | ||
|
|
@@ -478,37 +481,41 @@ def check_suggestion_add( | |
|
|
||
| @register_perm("upload.perform") | ||
| def check_upload( | ||
| user: User, permission: str, translation: Translation | ||
| user: User, permission: str, obj: Translation | ProjectLanguage | ||
| ) -> bool | PermissionResult: | ||
| """ | ||
| Check whether user can perform any upload operation. | ||
|
|
||
| The actual check for the method is implemented in | ||
| weblate.trans.util.check_upload_method_permissions. | ||
| """ | ||
| # Source upload | ||
| if translation.is_source and not user.has_perm("source.edit", translation): | ||
| return Denied(gettext("Insufficient privileges for editing source strings.")) | ||
| # Bilingual source translations | ||
| if ( | ||
| translation.is_source | ||
| and not translation.is_template | ||
| and not issubclass(translation.component.file_format_cls, BilingualUpdateMixin) | ||
| ): | ||
| return Denied( | ||
| gettext("The file format does not support updating source strings.") | ||
| ) | ||
| if translation.component.is_glossary: | ||
| permission = "glossary.upload" | ||
| return check_can_edit(user, permission, translation) and ( | ||
| if isinstance(obj, Translation): | ||
| # Source upload | ||
| if obj.is_source and not user.has_perm("source.edit", obj): | ||
| return Denied( | ||
| gettext("Insufficient privileges for editing source strings.") | ||
| ) | ||
| # Bilingual source translations | ||
| if ( | ||
| obj.is_source | ||
| and not obj.is_template | ||
| and not issubclass(obj.component.file_format_cls, BilingualUpdateMixin) | ||
| ): | ||
| return Denied( | ||
| gettext("The file format does not support updating source strings.") | ||
| ) | ||
| if obj.component.is_glossary: | ||
| permission = "glossary.upload" | ||
|
|
||
| return check_can_edit(user, permission, obj) and ( | ||
| # Normal upload | ||
| check_edit_approved(user, "unit.edit", translation) | ||
| check_edit_approved(user, "unit.edit", obj) | ||
| # Suggestion upload | ||
| or check_suggestion_add(user, "suggestion.add", translation) | ||
| or check_suggestion_add(user, "suggestion.add", obj) | ||
| # Add upload | ||
| or check_suggestion_add(user, "unit.add", translation) | ||
| or check_suggestion_add(user, "unit.add", obj) | ||
| # Source upload | ||
| or translation.is_source | ||
| or (isinstance(obj, Translation) and obj.is_source) | ||
| ) | ||
|
Comment on lines
+510
to
519
|
||
|
|
||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,6 +4,7 @@ | |
|
|
||
| {% block nav_pills %} | ||
| {% perm 'project.edit' object.project as user_can_edit_project %} | ||
| {% perm 'upload.perform' object as user_can_upload_translation %} | ||
|
|
||
| <ul class="nav nav-pills"> | ||
| <li class="nav-item"> | ||
|
|
@@ -63,6 +64,11 @@ | |
| href="{% url 'download' path=object.get_url_path %}?format=zip:xlsx" | ||
| title="{% translate "Download for offline translation." %}">{% blocktranslate %}Download translations as XLSX in a ZIP file{% endblocktranslate %}</a> | ||
| </li> | ||
| {% if user_can_upload_translation %} | ||
| <li> | ||
| <a class="dropdown-item" data-bs-target="#upload" data-bs-toggle="tab">{% translate "Upload translation" %}</a> | ||
| </li> | ||
| {% endif %} | ||
|
Comment on lines
+67
to
+71
|
||
| </ul> | ||
| </li> | ||
| <li class="nav-item dropdown"> | ||
|
|
@@ -127,6 +133,7 @@ | |
| {% announcements language=language project=project %} | ||
| {% perm 'project.edit' object.project as user_can_edit_project %} | ||
| {% get_translate_url object as translate_url %} | ||
| {% perm 'upload.perform' object as user_can_upload_translation %} | ||
|
|
||
| <div class="tab-content"> | ||
|
|
||
|
|
@@ -212,6 +219,29 @@ <h4 class="card-title"> | |
| </div> | ||
| {% endif %} | ||
|
|
||
| {% if user_can_upload_translation %} | ||
| <div class="tab-pane" id="upload"> | ||
| <div class="card"> | ||
| <div class="card-header"> | ||
| <h4 class="card-title"> | ||
| {% documentation_icon 'user/files' 'upload' right=True %} | ||
| {% translate "Upload" %} | ||
| </h4> | ||
| </div> | ||
| <div class="card-body"> | ||
| <p> | ||
| {% blocktranslate trimmed %} | ||
| Project-wide uploads are currently not supported. Translation | ||
| files need to be uploaded on the individual translations. Switch | ||
| to the "Components" tab above, open the desired component, and | ||
| perform the upload there. | ||
| {% endblocktranslate %} | ||
| </p> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| {% endif %} | ||
|
|
||
| {% if announcement_form %} | ||
| <div class="tab-pane" id="announcement"> | ||
| <form action="{% url 'announcement' path=object.get_url_path %}" method="post"> | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -1106,6 +1106,10 @@ def __str__(self) -> str: | |||||||||||||||||||||||||||||||||||||||||
| def enable_review(self) -> bool: | ||||||||||||||||||||||||||||||||||||||||||
| return self.project.enable_review | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| @property | ||||||||||||||||||||||||||||||||||||||||||
| def enable_suggestions(self) -> bool: | ||||||||||||||||||||||||||||||||||||||||||
| return True | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+1111
to
+1112
|
||||||||||||||||||||||||||||||||||||||||||
| return True | |
| """Return whether suggestions are enabled for this project-language. | |
| Suggestions are considered enabled if any related component for this | |
| project-language has suggestions enabled, or if workflow settings | |
| explicitly enable them. This avoids advertising suggestions in the UI | |
| when none of the components actually support them. | |
| """ | |
| # Check per-component configuration via related translations. | |
| for translation in self.translation_set: | |
| component = getattr(translation, "component", None) | |
| if component is not None and getattr(component, "enable_suggestions", False): | |
| return True | |
| # Fallback to workflow settings, if they define suggestion behavior. | |
| workflow = self.workflow_settings | |
| if workflow is not None and hasattr(workflow, "enable_suggestions"): | |
| return bool(getattr(workflow, "enable_suggestions")) | |
| return False |
Uh oh!
There was an error while loading. Please reload this page.