diff --git a/README.rst b/README.rst index 38d426bb..e14d3ed6 100644 --- a/README.rst +++ b/README.rst @@ -236,6 +236,13 @@ cached.):: obj = MyModel.objects.first() url = obj.link.url +A ``LinkField`` used inside a CMS plugin will automatically show internal link targets in +the language of the plugin (which might differ from the edit dialog's language). This +follows the principle the all content in the dialog is shown in the object's language. + +If you use ``LinkField`` in your own models, the default will be the current language. + + Link models ----------- diff --git a/djangocms_link/admin.py b/djangocms_link/admin.py index 572198e2..f38ea590 100644 --- a/djangocms_link/admin.py +++ b/djangocms_link/admin.py @@ -139,17 +139,17 @@ def get_reference(self, request: HttpRequest) -> JsonResponse: obj = get_manager(model).get(pk=pk) if model_str == "cms.page": obj.__link_text__ = obj.get_admin_content(language, fallback=True).title - return JsonResponse(self.serialize_result(obj)) + return JsonResponse(self.serialize_result(obj) or {}) elif model_str == "cms.page": obj = get_manager(model).get(pk=pk) obj.__link_text__ = obj.get_title(language, fallback=True) - return JsonResponse(self.serialize_result(obj)) + return JsonResponse(self.serialize_result(obj) or {}) if hasattr(model_admin, "get_link_queryset"): obj = model_admin.get_link_queryset(self.request, None).get(pk=pk) else: obj = model_admin.get_queryset(self.request).get(pk=pk) - return JsonResponse(self.serialize_result(obj)) + return JsonResponse(self.serialize_result(obj) or {}) except Exception as e: return JsonResponse({"error": str(e)}) @@ -166,7 +166,9 @@ def get_optgroups(self, context): "text": previous_model.capitalize(), "children": [], } - model["children"].append(self.serialize_result(obj)) + data = self.serialize_result(obj) + if data: # Only append if serialization was successful + model["children"].append(data) if model: results.append(model) return results @@ -181,12 +183,16 @@ def serialize_result(self, obj: Model) -> dict: obj.__link_text__ = obj.get_admin_content(self.language).title indentation = UNICODE_SPACE * (max(getattr(obj, "__depth__", 1), 1) - 1) - return { - "id": f"{obj._meta.app_label}.{obj._meta.model_name}:{obj.pk}", - "text": indentation + (getattr(obj, "__link_text__", str(obj)) or str(obj)), - "url": obj.get_absolute_url(), - "verbose_name": str(obj._meta.verbose_name).capitalize(), - } + url = obj.get_absolute_url() + text = getattr(obj, "__link_text__", str(obj)) or str(obj) + if url and text: + return { + "id": f"{obj._meta.app_label}.{obj._meta.model_name}:{obj.pk}", + "text": indentation + text, + "url": url, + "verbose_name": str(obj._meta.verbose_name).capitalize(), + } + return None def get_queryset(self) -> QuerySet: """Return queryset based on ModelAdmin.get_search_results().""" diff --git a/djangocms_link/cms_plugins.py b/djangocms_link/cms_plugins.py index cd42e21d..7d9babf2 100644 --- a/djangocms_link/cms_plugins.py +++ b/djangocms_link/cms_plugins.py @@ -1,13 +1,41 @@ +from __future__ import annotations + from django.contrib.sites.shortcuts import get_current_site +from django.db import models from django.utils.translation import gettext_lazy as _ from cms.plugin_base import CMSPluginBase from cms.plugin_pool import plugin_pool +from djangocms_link.fields import LinkFormField + from .helpers import get_link from .models import Link +def patch(original: callable) -> callable: + """ + Patch the get_form method of CMSPluginBase to ensure that the + 'language' attribute is set on the link widget's subwidgets in the form. + This is necessary for the link field to work correctly with multilingual sites and + shows the internal link target in the correct plugin language. + """ + def get_form(self, request, obj: models.Model | None = None, change: bool = False, **kwargs): + form = original(self, request, obj=obj, change=change, **kwargs) + + language = getattr(obj, "language", None) if obj else request.GET.get("plugin_language", None) + for field in form.base_fields.values(): + if isinstance(field, LinkFormField): + for widget in field.widget.widgets: + widget.language = language + return form + + return get_form + + +CMSPluginBase.get_form = patch(CMSPluginBase.get_form) + + class LinkPlugin(CMSPluginBase): model = Link name = _("Link") diff --git a/djangocms_link/fields.py b/djangocms_link/fields.py index a2ed7ee8..744f33d5 100644 --- a/djangocms_link/fields.py +++ b/djangocms_link/fields.py @@ -10,8 +10,10 @@ from django.db import models from django.db.models import JSONField, ManyToOneRel from django.forms import Field, MultiWidget, Select, TextInput, URLInput +from django.utils.encoding import force_str from django.utils.translation import get_language from django.utils.translation import gettext_lazy as _ +from django.utils.translation import override from cms.utils.urlutils import admin_reverse @@ -31,8 +33,9 @@ class LinkAutoCompleteWidget(AutocompleteSelect): - def __init__(self, attrs: dict | None = None): + def __init__(self, attrs: dict | None = None, language: str | None = None): super().__init__(None, None, attrs) + self.language = language def get_internal_obj(self, values: list[str | None]) -> list[models.Model | None]: internal_obj = [] @@ -46,29 +49,31 @@ def get_internal_obj(self, values: list[str | None]) -> list[models.Model | None return internal_obj def optgroups(self, name: str, value: str, attr: str | None = None): - default = (None, [], 0) - groups = [default] - has_selected = False - selected_choices = set(value) - if not self.is_required and not self.allow_multiple_selected: - default[1].append(self.create_option(name, "", "", False, 0)) - - for option_value, option_label in zip(value, self.get_internal_obj(value)): - selected = str(option_value) in value and ( - has_selected is False or self.allow_multiple_selected - ) - has_selected |= selected - index = len(default[1]) - subgroup = default[1] - subgroup.append( - self.create_option( - name, option_value, option_label, selected_choices, index + with override(self.language or get_language()): + default = (None, [], 0) + groups = [default] + has_selected = False + selected_choices = set(value) + if not self.is_required and not self.allow_multiple_selected: + default[1].append(self.create_option(name, "", "", False, 0)) + + for option_value, option_label in zip(value, self.get_internal_obj(value)): + selected = str(option_value) in value and ( + has_selected is False or self.allow_multiple_selected + ) + has_selected |= selected + index = len(default[1]) + subgroup = default[1] + subgroup.append( + self.create_option( + name, option_value, force_str(option_label), selected_choices, index + ) ) - ) return groups def get_url(self): - return admin_reverse("djangocms_link_link_urls") + reverse = admin_reverse("djangocms_link_link_urls") + return f"{reverse}?language={self.language}" if self.language else reverse def build_attrs(self, base_attrs: dict, extra_attrs: dict | None = None) -> dict: """ @@ -233,7 +238,7 @@ class Media: js = ("djangocms_link/link-widget.js",) css = {"all": ("djangocms_link/link-widget.css",)} - def __init__(self, site_selector: bool | None = None): + def __init__(self, site_selector: bool | None = None, language: str | None = None): if site_selector is None: site_selector = LinkWidget.default_site_selector @@ -242,22 +247,24 @@ def __init__(self, site_selector: bool | None = None): for key, widget in _available_widgets.items() if key == "always" or _mapping[key] in link_types ] - if site_selector and "internal_link" in allowed_link_types: + if "internal_link" in allowed_link_types: index = next( i for i, widget in enumerate(widgets) if widget.attrs.get("widget") == "internal_link" ) - widgets.insert( - index, - SiteAutocompleteSelect( - attrs={ - "class": "js-link-site-widget", - "widget": "site", - "data-placeholder": _("Select site"), - }, - ), - ) # Site selector + widgets[index].language = language # Pass on language to the internal link widget + if site_selector: + widgets.insert( + index, + SiteAutocompleteSelect( + attrs={ + "class": "js-link-site-widget", + "widget": "site", + "data-placeholder": _("Select site"), + }, + ), + ) # Site selector # Remember which widget expets its content at which position self.data_pos = { @@ -287,7 +294,6 @@ def get_context(self, name: str, value: str | None, attrs: dict) -> dict: class LinkFormField(Field): - widget = LinkWidget external_link_validators = [ ExtendedURLValidator(allowed_link_types=allowed_link_types) ] @@ -300,6 +306,7 @@ class LinkFormField(Field): def __init__(self, *args, **kwargs): kwargs.setdefault("help_text", _("Select a link type and provide a link.")) kwargs.setdefault("initial", {}) + kwargs.setdefault("widget", LinkWidget(language=kwargs.pop("language", None))) kwargs.pop("encoder", None) # Passed from LinkField's JSONField parent class kwargs.pop("decoder", None) # but not needed super().__init__(*args, **kwargs) diff --git a/djangocms_link/locale/de/LC_MESSAGES/django.mo b/djangocms_link/locale/de/LC_MESSAGES/django.mo index a4939469..22e5bf4d 100644 Binary files a/djangocms_link/locale/de/LC_MESSAGES/django.mo and b/djangocms_link/locale/de/LC_MESSAGES/django.mo differ diff --git a/djangocms_link/locale/de/LC_MESSAGES/django.po b/djangocms_link/locale/de/LC_MESSAGES/django.po index 73279e04..5f45a69a 100644 --- a/djangocms_link/locale/de/LC_MESSAGES/django.po +++ b/djangocms_link/locale/de/LC_MESSAGES/django.po @@ -4,18 +4,18 @@ # FIRST AUTHOR , YEAR. # # Translators: +# Angelo Dini , 2016 # danielastreuli , 2016 -# Angelo Dini , 2019 -# Fabian Braun , 2024 +# Fabian Braun , 2025 # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-10-27 14:11+0100\n" +"POT-Creation-Date: 2025-07-26 23:36+0200\n" "PO-Revision-Date: 2016-09-15 09:08+0000\n" -"Last-Translator: Fabian Braun , 2024\n" +"Last-Translator: Fabian Braun , 2025\n" "Language-Team: German (https://app.transifex.com/divio/teams/58664/de/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -23,49 +23,53 @@ msgstr "" "Language: de\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: djangocms_link/apps.py:7 +#: admin.py:105 +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" +"Page-Parameter ist nicht \"last\" und kann nicht in eine ganze Zahl " +"konvertiert werden." + +#: apps.py:10 msgid "django CMS Link" msgstr "django CMS Link" -#: djangocms_link/cms_plugins.py:15 djangocms_link/models.py:73 +#: cms_plugins.py:41 models.py:70 msgid "Link" msgstr "Link" -#: djangocms_link/cms_plugins.py:27 +#: cms_plugins.py:64 msgid "Advanced settings" msgstr "Erweiterte Einstellungen" -#: djangocms_link/fields.py:26 djangocms_link/forms.py:15 +#: fields.py:155 msgid "Internal link" msgstr "Interner Link" -#: djangocms_link/fields.py:27 +#: fields.py:156 msgid "External link/anchor" msgstr "Externer Link/Anker" -#: djangocms_link/fields.py:30 +#: fields.py:159 msgid "File link" -msgstr "Datei Link" +msgstr "Datei-Link" -#: djangocms_link/fields.py:169 +#: fields.py:191 msgid "No destination selected. Use the dropdown to select a destination." msgstr "Kein Ziel ausgewählt. Ziel im Dropdown-Menü auswählen." -#: djangocms_link/fields.py:175 +#: fields.py:198 msgid "https://example.com or #anchor" msgstr "https://beispiel.de oder #anker" -#: djangocms_link/fields.py:177 +#: fields.py:200 msgid "" -"Provide a link to an external URL, including the schema such as 'https://', " -"'tel:', or 'mailto:'. Optionally, add an #anchor (including the #) to scroll" -" to." +"Provide a link to an external URL, including the schema such as {}. " +"Optionally, add an #anchor (including the #) to scroll to." msgstr "" -"Link zu einer externen URL angeben, inklusive Schema wie z.B. \"https://\", " -"\"tel:\" oder \"mailto:\". Optional einen \"#anker\" hinzufügen (inklusive " -"#)." +"Link zu einer externen URL eingeben, inkl. Schema wie z.B. {}. Optional " +"#Anker hinzufügen (inkl. #)." -#: djangocms_link/fields.py:186 +#: fields.py:209 msgid "" "Select from available internal destinations. Optionally, add an anchor to " "scroll to." @@ -73,78 +77,78 @@ msgstr "" "Aus den verfügbaren internen Zielen auswählen. Optional einen Anker " "hinzufügen." -#: djangocms_link/fields.py:188 +#: fields.py:211 msgid "Select internal destination" msgstr "Internes Ziel auswählen" -#: djangocms_link/fields.py:194 +#: fields.py:217 msgid "#anchor" msgstr "#anker" -#: djangocms_link/fields.py:195 +#: fields.py:218 msgid "Provide an anchor to scroll to." msgstr "Anker angeben, der angesprungen wird." -#: djangocms_link/fields.py:206 +#: fields.py:228 msgid "Select a file as destination." msgstr "Datei als Ziel auswählen." -#: djangocms_link/fields.py:215 +#: fields.py:266 msgid "Select site" msgstr "Site auswählen" -#: djangocms_link/fields.py:249 +#: fields.py:309 msgid "Select a link type and provide a link." msgstr "Link-Typ auswählen und Ziel angeben." -#: djangocms_link/models.py:24 +#: models.py:25 msgid "Default" msgstr "Standard" -#: djangocms_link/models.py:41 +#: models.py:38 msgid "Open in new window" msgstr "In neuem Fenster öffnen" -#: djangocms_link/models.py:42 +#: models.py:39 msgid "Open in same window" msgstr "Im gleichen Fenster öffnen" -#: djangocms_link/models.py:43 +#: models.py:40 msgid "Delegate to parent" msgstr "Zum nächsten Fenster delegieren" -#: djangocms_link/models.py:44 +#: models.py:41 msgid "Delegate to top" msgstr "Zum obersten Fenster delegieren" -#: djangocms_link/models.py:61 +#: models.py:58 msgid "Template" msgstr "Template" -#: djangocms_link/models.py:67 +#: models.py:64 msgid "Display name" msgstr "Anzeigename" -#: djangocms_link/models.py:77 +#: models.py:74 msgid "Target" msgstr "Verweis" -#: djangocms_link/models.py:83 +#: models.py:80 msgid "Attributes" msgstr "Attribute" -#: djangocms_link/models.py:109 +#: models.py:106 msgid "" msgstr "" -#: djangocms_link/models.py:118 +#: models.py:115 msgid "Link is required." msgstr "Der Link ist ein Pflichtfeld." -#: djangocms_link/validators.py:50 +#: validators.py:61 msgid "Enter a valid anchor" msgstr "Gültigen Anker angeben" -#: djangocms_link/validators.py:84 +#: validators.py:104 msgid "Enter a valid phone number" msgstr "Gültige Telefonnummer angeben" diff --git a/djangocms_link/locale/en/LC_MESSAGES/django.po b/djangocms_link/locale/en/LC_MESSAGES/django.po index a4603d79..ef1a7547 100644 --- a/djangocms_link/locale/en/LC_MESSAGES/django.po +++ b/djangocms_link/locale/en/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-10-27 14:11+0100\n" +"POT-Creation-Date: 2025-07-26 23:36+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,123 +17,127 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: djangocms_link/apps.py:7 + +#: admin.py:105 +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "" + +#: apps.py:10 msgid "django CMS Link" msgstr "" -#: djangocms_link/cms_plugins.py:15 djangocms_link/models.py:73 +#: cms_plugins.py:41 models.py:70 msgid "Link" -msgstr "Link" +msgstr "" -#: djangocms_link/cms_plugins.py:27 +#: cms_plugins.py:64 msgid "Advanced settings" -msgstr "Advanced settings" +msgstr "" -#: djangocms_link/fields.py:26 djangocms_link/forms.py:15 +#: fields.py:155 msgid "Internal link" -msgstr "Internal link" +msgstr "" -#: djangocms_link/fields.py:27 +#: fields.py:156 msgid "External link/anchor" msgstr "" -#: djangocms_link/fields.py:30 +#: fields.py:159 msgid "File link" msgstr "" -#: djangocms_link/fields.py:169 +#: fields.py:191 msgid "No destination selected. Use the dropdown to select a destination." msgstr "" -#: djangocms_link/fields.py:175 +#: fields.py:198 msgid "https://example.com or #anchor" -msgstr "https://example.com or #anchor" +msgstr "" -#: djangocms_link/fields.py:177 +#: fields.py:200 msgid "" -"Provide a link to an external URL, including the schema such as 'https://', " -"'tel:', or 'mailto:'. Optionally, add an #anchor (including the #) to scroll " -"to." +"Provide a link to an external URL, including the schema such as {}. " +"Optionally, add an #anchor (including the #) to scroll to." msgstr "" -#: djangocms_link/fields.py:186 +#: fields.py:209 msgid "" "Select from available internal destinations. Optionally, add an anchor to " "scroll to." msgstr "" -#: djangocms_link/fields.py:188 +#: fields.py:211 msgid "Select internal destination" msgstr "" -#: djangocms_link/fields.py:194 +#: fields.py:217 msgid "#anchor" msgstr "" -#: djangocms_link/fields.py:195 +#: fields.py:218 msgid "Provide an anchor to scroll to." msgstr "" -#: djangocms_link/fields.py:206 +#: fields.py:228 msgid "Select a file as destination." msgstr "" -#: djangocms_link/fields.py:215 +#: fields.py:266 msgid "Select site" -msgstr "Select site" +msgstr "" -#: djangocms_link/fields.py:249 +#: fields.py:309 msgid "Select a link type and provide a link." msgstr "" -#: djangocms_link/models.py:24 +#: models.py:25 msgid "Default" msgstr "" -#: djangocms_link/models.py:41 +#: models.py:38 msgid "Open in new window" msgstr "" -#: djangocms_link/models.py:42 +#: models.py:39 msgid "Open in same window" msgstr "" -#: djangocms_link/models.py:43 +#: models.py:40 msgid "Delegate to parent" msgstr "" -#: djangocms_link/models.py:44 +#: models.py:41 msgid "Delegate to top" msgstr "" -#: djangocms_link/models.py:61 +#: models.py:58 msgid "Template" msgstr "" -#: djangocms_link/models.py:67 +#: models.py:64 msgid "Display name" msgstr "" -#: djangocms_link/models.py:77 +#: models.py:74 msgid "Target" msgstr "" -#: djangocms_link/models.py:83 +#: models.py:80 msgid "Attributes" msgstr "" -#: djangocms_link/models.py:109 +#: models.py:106 msgid "" msgstr "" -#: djangocms_link/models.py:118 +#: models.py:115 msgid "Link is required." -msgstr "Link is required." +msgstr "" -#: djangocms_link/validators.py:50 +#: validators.py:61 msgid "Enter a valid anchor" -msgstr "Enter a valid anchor" +msgstr "" -#: djangocms_link/validators.py:84 +#: validators.py:104 msgid "Enter a valid phone number" -msgstr "Enter a valid phone number" +msgstr "" diff --git a/djangocms_link/locale/fr/LC_MESSAGES/django.mo b/djangocms_link/locale/fr/LC_MESSAGES/django.mo index f8a972ba..b5d999e9 100644 Binary files a/djangocms_link/locale/fr/LC_MESSAGES/django.mo and b/djangocms_link/locale/fr/LC_MESSAGES/django.mo differ diff --git a/djangocms_link/locale/fr/LC_MESSAGES/django.po b/djangocms_link/locale/fr/LC_MESSAGES/django.po index 7bac24c0..23f41bed 100644 --- a/djangocms_link/locale/fr/LC_MESSAGES/django.po +++ b/djangocms_link/locale/fr/LC_MESSAGES/django.po @@ -6,15 +6,16 @@ # Translators: # a270031086f2a0d3514bc0cb507b48f6, 2019 # Florian Delizy , 2021 +# Fabian Braun , 2025 # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-10-27 14:11+0100\n" +"POT-Creation-Date: 2025-07-26 23:36+0200\n" "PO-Revision-Date: 2016-09-15 09:08+0000\n" -"Last-Translator: Florian Delizy , 2021\n" +"Last-Translator: Fabian Braun , 2025\n" "Language-Team: French (https://app.transifex.com/divio/teams/58664/fr/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -22,123 +23,133 @@ msgstr "" "Language: fr\n" "Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n" -#: djangocms_link/apps.py:7 +#: admin.py:105 +msgid "Page is not “last”, nor can it be converted to an int." +msgstr "La page n'est pas «last», et ne peut pas être convertie en entier." + +#: apps.py:10 msgid "django CMS Link" -msgstr "" +msgstr "django CMS Lien" -#: djangocms_link/cms_plugins.py:15 djangocms_link/models.py:73 +#: cms_plugins.py:41 models.py:70 msgid "Link" msgstr "Lien" -#: djangocms_link/cms_plugins.py:27 +#: cms_plugins.py:64 msgid "Advanced settings" msgstr "Réglages avancés" -#: djangocms_link/fields.py:26 djangocms_link/forms.py:15 +#: fields.py:155 msgid "Internal link" msgstr "Lien interne" -#: djangocms_link/fields.py:27 +#: fields.py:156 msgid "External link/anchor" -msgstr "" +msgstr "Lien externe/ancre" -#: djangocms_link/fields.py:30 +#: fields.py:159 msgid "File link" msgstr "Lien vers le fichier" -#: djangocms_link/fields.py:169 +#: fields.py:191 msgid "No destination selected. Use the dropdown to select a destination." msgstr "" +"Aucune destination sélectionnée. Utilisez le menu déroulant pour " +"sélectionner une destination." -#: djangocms_link/fields.py:175 +#: fields.py:198 msgid "https://example.com or #anchor" -msgstr "" +msgstr "https://example.com ou #ancre" -#: djangocms_link/fields.py:177 +#: fields.py:200 msgid "" -"Provide a link to an external URL, including the schema such as 'https://', " -"'tel:', or 'mailto:'. Optionally, add an #anchor (including the #) to scroll" -" to." +"Provide a link to an external URL, including the schema such as {}. " +"Optionally, add an #anchor (including the #) to scroll to." msgstr "" +"Fournissez un lien vers une URL externe, y compris le schéma tel que {}. " +"Vous pouvez également ajouter une #ancre (y compris le #) pour faire défiler" +" jusqu'à celle-ci." -#: djangocms_link/fields.py:186 +#: fields.py:209 msgid "" "Select from available internal destinations. Optionally, add an anchor to " "scroll to." msgstr "" +"Sélectionnez parmi les destinations internes disponibles. Vous pouvez " +"également ajouter une ancre pour faire défiler jusqu'à celle-ci." -#: djangocms_link/fields.py:188 +#: fields.py:211 msgid "Select internal destination" -msgstr "" +msgstr "Sélectionnez une destination interne" -#: djangocms_link/fields.py:194 +#: fields.py:217 msgid "#anchor" -msgstr "" +msgstr "#ancre" -#: djangocms_link/fields.py:195 +#: fields.py:218 msgid "Provide an anchor to scroll to." -msgstr "" +msgstr "Fournissez une ancre pour faire défiler jusqu'à celle-ci." -#: djangocms_link/fields.py:206 +#: fields.py:228 msgid "Select a file as destination." -msgstr "" +msgstr "Sélectionnez un fichier comme destination." -#: djangocms_link/fields.py:215 +#: fields.py:266 msgid "Select site" -msgstr "" +msgstr "Sélectionnez le site" -#: djangocms_link/fields.py:249 +#: fields.py:309 msgid "Select a link type and provide a link." -msgstr "" +msgstr "Sélectionnez un type de lien et fournissez un lien." -#: djangocms_link/models.py:24 +#: models.py:25 msgid "Default" msgstr "Défaut" -#: djangocms_link/models.py:41 +#: models.py:38 msgid "Open in new window" msgstr "Ouvrir dans une nouvelle fenêtre" -#: djangocms_link/models.py:42 +#: models.py:39 msgid "Open in same window" msgstr "Ouvrir dans la même fenêtre" -#: djangocms_link/models.py:43 +#: models.py:40 msgid "Delegate to parent" msgstr "Déléguer au parent" -#: djangocms_link/models.py:44 +#: models.py:41 msgid "Delegate to top" msgstr "Délégué au sommet" -#: djangocms_link/models.py:61 +#: models.py:58 msgid "Template" msgstr "Modèle" -#: djangocms_link/models.py:67 +#: models.py:64 msgid "Display name" msgstr "Afficher un nom" -#: djangocms_link/models.py:77 +#: models.py:74 msgid "Target" msgstr "Cible" -#: djangocms_link/models.py:83 +#: models.py:80 msgid "Attributes" msgstr "Les attributs" -#: djangocms_link/models.py:109 +#: models.py:106 msgid "" msgstr "" -#: djangocms_link/models.py:118 +#: models.py:115 msgid "Link is required." -msgstr "" +msgstr "Le lien est requis." -#: djangocms_link/validators.py:50 +#: validators.py:61 msgid "Enter a valid anchor" -msgstr "" +msgstr "Entrez une ancre valide" -#: djangocms_link/validators.py:84 +#: validators.py:104 msgid "Enter a valid phone number" -msgstr "" +msgstr "Entrez un numéro de téléphone valide" diff --git a/djangocms_link/locale/nl/LC_MESSAGES/django.mo b/djangocms_link/locale/nl/LC_MESSAGES/django.mo index 8b272cd3..eb171a55 100644 Binary files a/djangocms_link/locale/nl/LC_MESSAGES/django.mo and b/djangocms_link/locale/nl/LC_MESSAGES/django.mo differ diff --git a/djangocms_link/locale/nl/LC_MESSAGES/django.po b/djangocms_link/locale/nl/LC_MESSAGES/django.po index 4b6116f6..f9df9b2f 100644 --- a/djangocms_link/locale/nl/LC_MESSAGES/django.po +++ b/djangocms_link/locale/nl/LC_MESSAGES/django.po @@ -7,15 +7,16 @@ # Angelo Dini , 2016 # Evelijn Saaltink , 2016 # Heimen Stoffels , 2019 +# Stefan van den Eertwegh , 2025 # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-10-27 14:11+0100\n" +"POT-Creation-Date: 2025-07-26 23:36+0200\n" "PO-Revision-Date: 2016-09-15 09:08+0000\n" -"Last-Translator: Heimen Stoffels , 2019\n" +"Last-Translator: Stefan van den Eertwegh , 2025\n" "Language-Team: Dutch (https://app.transifex.com/divio/teams/58664/nl/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -23,123 +24,133 @@ msgstr "" "Language: nl\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: djangocms_link/apps.py:7 -msgid "django CMS Link" +#: admin.py:105 +msgid "Page is not “last”, nor can it be converted to an int." msgstr "" +"Pagina is niet de “laatste” en kan ook niet worden omgezet naar een int." + +#: apps.py:10 +msgid "django CMS Link" +msgstr "django CMS Link" -#: djangocms_link/cms_plugins.py:15 djangocms_link/models.py:73 +#: cms_plugins.py:41 models.py:70 msgid "Link" msgstr "Link" -#: djangocms_link/cms_plugins.py:27 +#: cms_plugins.py:64 msgid "Advanced settings" msgstr "Geavanceerde instellingen" -#: djangocms_link/fields.py:26 djangocms_link/forms.py:15 +#: fields.py:155 msgid "Internal link" msgstr "Interne link" -#: djangocms_link/fields.py:27 +#: fields.py:156 msgid "External link/anchor" -msgstr "" +msgstr "Externe link/anchor" -#: djangocms_link/fields.py:30 +#: fields.py:159 msgid "File link" msgstr "Bestandslink" -#: djangocms_link/fields.py:169 +#: fields.py:191 msgid "No destination selected. Use the dropdown to select a destination." msgstr "" +"Geen bestemming geselecteerd. Gebruik de dropdown om een bestemming te " +"selecteren." -#: djangocms_link/fields.py:175 +#: fields.py:198 msgid "https://example.com or #anchor" -msgstr "" +msgstr "https://example.com of #anchor" -#: djangocms_link/fields.py:177 +#: fields.py:200 msgid "" -"Provide a link to an external URL, including the schema such as 'https://', " -"'tel:', or 'mailto:'. Optionally, add an #anchor (including the #) to scroll" -" to." +"Provide a link to an external URL, including the schema such as {}. " +"Optionally, add an #anchor (including the #) to scroll to." msgstr "" +"Geef een link naar een externe URL, inclusief het schema, zoals {}. Voeg " +"eventueel een #anker (inclusief #) toe om naartoe te scrollen." -#: djangocms_link/fields.py:186 +#: fields.py:209 msgid "" "Select from available internal destinations. Optionally, add an anchor to " "scroll to." msgstr "" +"Selecteer uit beschikbare interne bestemmingen. Voeg optioneel een anker toe" +" om naartoe te scrollen." -#: djangocms_link/fields.py:188 +#: fields.py:211 msgid "Select internal destination" -msgstr "" +msgstr "Selecteer interne bestemming" -#: djangocms_link/fields.py:194 +#: fields.py:217 msgid "#anchor" -msgstr "" +msgstr "#anker" -#: djangocms_link/fields.py:195 +#: fields.py:218 msgid "Provide an anchor to scroll to." -msgstr "" +msgstr "Zorg voor een anker waar naartoe gescrolld kan worden." -#: djangocms_link/fields.py:206 +#: fields.py:228 msgid "Select a file as destination." -msgstr "" +msgstr "Selecteer een bestand als bestemming." -#: djangocms_link/fields.py:215 +#: fields.py:266 msgid "Select site" -msgstr "" +msgstr "Selecteer site" -#: djangocms_link/fields.py:249 +#: fields.py:309 msgid "Select a link type and provide a link." -msgstr "" +msgstr "Selecteer een link type en voorzie deze van een link." -#: djangocms_link/models.py:24 +#: models.py:25 msgid "Default" msgstr "Standaard" -#: djangocms_link/models.py:41 +#: models.py:38 msgid "Open in new window" msgstr "Openen in nieuw venster" -#: djangocms_link/models.py:42 +#: models.py:39 msgid "Open in same window" msgstr "Openen in hetzelfde venster" -#: djangocms_link/models.py:43 +#: models.py:40 msgid "Delegate to parent" msgstr "Naar ouder delegeren" -#: djangocms_link/models.py:44 +#: models.py:41 msgid "Delegate to top" msgstr "Naar bovenkant delegeren" -#: djangocms_link/models.py:61 +#: models.py:58 msgid "Template" msgstr "Sjabloon" -#: djangocms_link/models.py:67 +#: models.py:64 msgid "Display name" msgstr "Getoonde naam" -#: djangocms_link/models.py:77 +#: models.py:74 msgid "Target" msgstr "Doel" -#: djangocms_link/models.py:83 +#: models.py:80 msgid "Attributes" msgstr "Eigenschappen" -#: djangocms_link/models.py:109 +#: models.py:106 msgid "" msgstr "" -#: djangocms_link/models.py:118 +#: models.py:115 msgid "Link is required." -msgstr "" +msgstr "Link is verreist." -#: djangocms_link/validators.py:50 +#: validators.py:61 msgid "Enter a valid anchor" -msgstr "" +msgstr "Type een geldig anker" -#: djangocms_link/validators.py:84 +#: validators.py:104 msgid "Enter a valid phone number" -msgstr "" +msgstr "Type een geldig telefoonnummer" diff --git a/djangocms_link/models.py b/djangocms_link/models.py index 61635211..cf2e6b56 100644 --- a/djangocms_link/models.py +++ b/djangocms_link/models.py @@ -9,6 +9,7 @@ from django.utils.encoding import force_str from django.utils.translation import gettext from django.utils.translation import gettext_lazy as _ +from django.utils.translation import override from cms.models import CMSPlugin @@ -100,7 +101,8 @@ def __str__(self): return self.name or str(self.pk) def get_short_description(self): - link = self.get_link() + with override(self.language): + link = self.get_link() if self.name and link: return f"{self.name} ({link})" return self.name or link or gettext("")