-
Notifications
You must be signed in to change notification settings - Fork 36
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1135 from digitalfabrik/feature/deepl
Add automatic translations via DeepL API
- Loading branch information
Showing
9 changed files
with
218 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
import logging | ||
import deepl | ||
|
||
from django.conf import settings | ||
from django.contrib import messages | ||
from django.utils.translation import ugettext as _ | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
class DeepLApi: | ||
""" | ||
DeepL API to auto translate selected posts. | ||
""" | ||
|
||
def __init__(self): | ||
""" | ||
Initialize the DeepL client | ||
""" | ||
self.translator = deepl.Translator(settings.DEEPL_AUTH_KEY) | ||
|
||
def check_availability(self, request, language_slug): | ||
""" | ||
This function checks, if the selected language is supported by DeepL | ||
:param request: request that was sent to the server | ||
:type request: ~django.http.HttpRequest | ||
:param language_slug: current language slug | ||
:type language_slug: str | ||
:return: true or false | ||
:rtype: bool | ||
""" | ||
supported_source_languages = [ | ||
source_language.code.lower() | ||
for source_language in self.translator.get_source_languages() | ||
] | ||
supported_target_languages = [ | ||
target_languages.code.lower()[:2] | ||
for target_languages in self.translator.get_target_languages() | ||
] | ||
source_language = request.region.get_source_language(language_slug) | ||
return ( | ||
source_language | ||
and source_language.slug in supported_source_languages | ||
and language_slug in supported_target_languages | ||
) | ||
|
||
def deepl_translation(self, request, content_objects, language_slug, form_class): | ||
""" | ||
This functions gets the translation from DeepL | ||
:param request: passed request | ||
:type request: ~django.http.HttpRequest | ||
:param content_objects: passed content objects | ||
:type content_objects: ~django.db.models.query.QuerySet [ ~integreat_cms.cms.models.abstract_content_model.AbstractContentModel ] | ||
:param language_slug: current GUI language slug | ||
:type language_slug: str | ||
:param form_class: passed Form class of content type | ||
:type form_class: ~integreat_cms.cms.forms.custom_content_model_form.CustomContentModelForm | ||
""" | ||
# Get target language | ||
target_language = request.region.get_language_or_404(language_slug) | ||
source_language = request.region.get_source_language(language_slug) | ||
for content_object in content_objects: | ||
source_translation = content_object.get_translation(source_language.slug) | ||
if not source_translation: | ||
messages.error( | ||
request, | ||
_('No source translation could be found for {} "{}".').format( | ||
type(content_object)._meta.verbose_name.title(), | ||
content_object.best_translation.title, | ||
), | ||
) | ||
continue | ||
existing_target_translation = content_object.get_translation( | ||
target_language.slug | ||
) | ||
# For some languages, the DeepL client expects the BCP tag instead of the short language code | ||
if target_language.slug in ("en", "pt"): | ||
target_language_key = target_language.bcp47_tag | ||
else: | ||
target_language_key = target_language.slug | ||
target_title = self.translator.translate_text( | ||
source_translation.title, | ||
source_lang=source_language.slug, | ||
target_lang=target_language_key, | ||
) | ||
data = { | ||
"title": target_title, | ||
"status": existing_target_translation.status | ||
if existing_target_translation | ||
else source_translation.status, | ||
} | ||
if source_translation.content: | ||
data["content"] = self.translator.translate_text( | ||
source_translation.content, | ||
source_lang=source_language.slug, | ||
target_lang=target_language_key, | ||
) | ||
# for pois adds a short description | ||
if hasattr(source_translation, "short_description"): | ||
data["short_description"] = self.translator.translate_text( | ||
source_translation.short_description, | ||
source_lang=source_language.slug, | ||
target_lang=target_language_key, | ||
) | ||
content_translation_form = form_class( | ||
data=data, | ||
instance=existing_target_translation, | ||
additional_instance_attributes={ | ||
"creator": request.user, | ||
"language": target_language, | ||
source_translation.foreign_field(): content_object, | ||
}, | ||
) | ||
# Validate event translation | ||
if content_translation_form.is_valid(): | ||
content_translation_form.save() | ||
logger.debug( | ||
"Successfully translated for: %r", content_translation_form.instance | ||
) | ||
messages.success( | ||
request, | ||
_('{} "{}" has been successfully translated.').format( | ||
type(content_object)._meta.verbose_name.title(), | ||
source_translation.title, | ||
), | ||
) | ||
else: | ||
logger.error( | ||
"Automatic translation for %r could not be created because of %r", | ||
content_object, | ||
content_translation_form.errors, | ||
) | ||
messages.error( | ||
request, | ||
_('{} "{}" could not be automatically translated.').format( | ||
type(content_object)._meta.verbose_name.title(), | ||
source_translation.title, | ||
), | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,7 +8,7 @@ msgid "" | |
msgstr "" | ||
"Project-Id-Version: 1.0\n" | ||
"Report-Msgid-Bugs-To: \n" | ||
"POT-Creation-Date: 2022-03-20 18:58+0000\n" | ||
"POT-Creation-Date: 2022-03-23 12:23+0000\n" | ||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" | ||
"Last-Translator: Integreat <[email protected]>\n" | ||
"Language-Team: Integreat <[email protected]>\n" | ||
|
@@ -3121,7 +3121,7 @@ msgstr "Feedback" | |
|
||
#: cms/templates/_base.html:181 | ||
#: cms/templates/push_notifications/push_notification_list.html:9 | ||
#: core/settings.py:712 | ||
#: core/settings.py:716 | ||
msgid "News" | ||
msgstr "Nachrichten" | ||
|
||
|
@@ -5699,19 +5699,21 @@ msgstr "" | |
"Adresse eingegeben haben, mit der Sie sich registriert haben, und überprüfen " | ||
"Sie Ihren Spam-Ordner." | ||
|
||
#: cms/views/bulk_action_views.py:123 | ||
msgid "Automatic translations are not fully implemented yet" | ||
msgstr "Automatische Übersetzungen sind noch nicht vollständig implementiert" | ||
|
||
#: cms/views/bulk_action_views.py:126 | ||
#: cms/views/bulk_action_views.py:124 | ||
msgid "Automatic translations are disabled" | ||
msgstr "Automatische Übersetzungen sind deaktiviert" | ||
|
||
#: cms/views/bulk_action_views.py:164 | ||
#: cms/views/bulk_action_views.py:137 | ||
msgid "This language is not supported by DeepL. Please try another language" | ||
msgstr "" | ||
"Diese Sprache wird von DeepL nicht unterstützt. Bitte versuchen Sie eine " | ||
"andere Sprache" | ||
|
||
#: cms/views/bulk_action_views.py:177 | ||
msgid "The selected {} were successfully archived" | ||
msgstr "Die ausgewählten {} wurden erfolgreich archiviert" | ||
|
||
#: cms/views/bulk_action_views.py:203 | ||
#: cms/views/bulk_action_views.py:216 | ||
msgid "The selected {} were successfully restored" | ||
msgstr "Die ausgewählten {} wurden erfolgreich wiederhergestellt" | ||
|
||
|
@@ -6599,6 +6601,18 @@ msgid "Superuser permissions need to be set by another superuser." | |
msgstr "" | ||
"Administratorrechte müssen von einem anderen Administrator vergeben werden." | ||
|
||
#: deepl_api/utils.py:74 | ||
msgid "No source translation could be found for {} \"{}\"." | ||
msgstr "Es konnte kein Quelltext für {} \"{}\" gefunden werden." | ||
|
||
#: deepl_api/utils.py:129 | ||
msgid "{} \"{}\" has been successfully translated." | ||
msgstr "{} \"{}\" wurde erfolgreich übersetzt" | ||
|
||
#: deepl_api/utils.py:142 | ||
msgid "{} \"{}\" could not be automatically translated." | ||
msgstr "{} \"{}\" konnte nicht automatisch übersetzt werden." | ||
|
||
#: xliff/utils.py:152 | ||
msgid "" | ||
"Page {} does not have a source translation in {} and therefore cannot be " | ||
|
@@ -6650,6 +6664,10 @@ msgstr "" | |
"Diese Seite konnte nicht importiert werden, da sie zu einer anderen Region " | ||
"gehört ({})." | ||
|
||
#~ msgid "Automatic translations are not fully implemented yet" | ||
#~ msgstr "" | ||
#~ "Automatische Übersetzungen sind noch nicht vollständig implementiert" | ||
|
||
#~ msgid "Filetype:" | ||
#~ msgstr "Dateityp:" | ||
|
||
|
@@ -6663,6 +6681,9 @@ msgstr "" | |
#~ msgid "Export XLIFF for translation to" | ||
#~ msgstr "Exportiere XLIFF für Übersetzung nach" | ||
|
||
#~ msgid "POI has been successfully translated" | ||
#~ msgstr "POI wurde erfolgreich übersetzt." | ||
|
||
#~ msgid "Access token to update the page content" | ||
#~ msgstr "Zugangs-Token um Seiten-Inhalte zu aktualisieren" | ||
|
||
|
@@ -6930,9 +6951,6 @@ msgstr "" | |
#~ msgid "Event was successfully created and published" | ||
#~ msgstr "Veranstaltung wurde erfolgreich erstellt und veröffentlicht" | ||
|
||
#~ msgid "Event was successfully created" | ||
#~ msgstr "Veranstaltung wurde erfolgreich erstellt" | ||
|
||
#~ msgid "Event translation was successfully created and published" | ||
#~ msgstr "" | ||
#~ "Veranstaltungsübersetzung wurde erfolgreich erstellt und veröffentlicht" | ||
|
@@ -8000,9 +8018,6 @@ msgstr "" | |
#~ msgid "POI was successfully created and published." | ||
#~ msgstr "POI wurde erfolgreich erstellt und veröffentlicht." | ||
|
||
#~ msgid "POI was successfully created." | ||
#~ msgstr "POI wurde erfolgreich erstellt." | ||
|
||
#~ msgid "POI was successfully published." | ||
#~ msgstr "POI wurde erfolgreich veröffentlicht." | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters